From d6deeb5f3b68345e07ea3b44692ef88c2f8c62e2 Mon Sep 17 00:00:00 2001 From: "U-N\\N" Date: Fri, 26 Jun 2020 23:01:14 +0200 Subject: [PATCH 01/41] use base_volume instead of volume --- src/iuse_actor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 31226576497d7..73069a4020575 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -2595,8 +2595,8 @@ bool repair_item_actor::handle_components( player &pl, const item &fix, // Round up if checking, but roll if actually consuming // TODO: should 250_ml be part of the cost_scaling? const int items_needed = std::max( 1, just_check ? - std::ceil( fix.volume() / 250_ml * cost_scaling ) : - roll_remainder( fix.volume() / 250_ml * cost_scaling ) ); + std::ceil( fix.base_volume() / 250_ml * cost_scaling ) : + roll_remainder( fix.base_volume() / 250_ml * cost_scaling ) ); std::function filter; if( fix.is_filthy() ) { From b9710b0436927bcfa468ea316b8a678cdc715ad6 Mon Sep 17 00:00:00 2001 From: Fris0uman Date: Sat, 27 Jun 2020 10:35:05 +0200 Subject: [PATCH 02/41] Fix loading character template --- src/newcharacter.cpp | 3 +++ src/savegame_json.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 6a907d3888a83..1ad16e7d335c2 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -435,6 +435,9 @@ bool avatar::create( character_type type, const std::string &tempname ) if( !load_template( tempname, points ) ) { return false; } + // TEMPORARY until 0.F + set_all_parts_hp_to_max(); + // We want to prevent recipes known by the template from being applied to the // new character. The recipe list will be rebuilt when entering the game. // Except if it is a character transfer template diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 508546774ca79..67c4aa268a39d 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -637,8 +637,12 @@ void Character::load( const JsonObject &data ) set_part_hp_cur( bodypart_id( "torso" ), hp_cur[1] ); set_part_hp_max( bodypart_id( "torso" ), hp_max[1] ); set_part_hp_cur( bodypart_id( "arm_l" ), hp_cur[2] ); + set_part_hp_max( bodypart_id( "arm_l" ), hp_max[2] ); + set_part_hp_cur( bodypart_id( "arm_r" ), hp_cur[3] ); set_part_hp_max( bodypart_id( "arm_r" ), hp_max[3] ); set_part_hp_cur( bodypart_id( "leg_l" ), hp_cur[4] ); + set_part_hp_max( bodypart_id( "leg_l" ), hp_max[4] ); + set_part_hp_cur( bodypart_id( "leg_r" ), hp_cur[5] ); set_part_hp_max( bodypart_id( "leg_r" ), hp_max[5] ); } From 41217d0630d76337269de08d0f022a1b0db15add Mon Sep 17 00:00:00 2001 From: John Candlebury Date: Sat, 27 Jun 2020 10:20:55 -0600 Subject: [PATCH 03/41] Item group organization --- .../Aftershock/itemgroups/bionics_groups.json | 44 +++ .../{items => itemgroups}/item_groups.json | 285 +++++++++++------- .../itemgroups/nuclear_reactor_groups.json | 31 ++ .../Aftershock/itemgroups/scrap_groups.json | 30 ++ .../itemgroups/titanium_groups.json | 89 ++++++ data/mods/Aftershock/items/monster_drops.json | 8 - data/mods/Aftershock/maps/item_groups.json | 243 --------------- .../{items => monsterdrops}/monsterdrops.json | 6 + 8 files changed, 370 insertions(+), 366 deletions(-) create mode 100644 data/mods/Aftershock/itemgroups/bionics_groups.json rename data/mods/Aftershock/{items => itemgroups}/item_groups.json (63%) create mode 100644 data/mods/Aftershock/itemgroups/nuclear_reactor_groups.json create mode 100644 data/mods/Aftershock/itemgroups/scrap_groups.json create mode 100644 data/mods/Aftershock/itemgroups/titanium_groups.json delete mode 100644 data/mods/Aftershock/items/monster_drops.json delete mode 100644 data/mods/Aftershock/maps/item_groups.json rename data/mods/Aftershock/{items => monsterdrops}/monsterdrops.json (93%) diff --git a/data/mods/Aftershock/itemgroups/bionics_groups.json b/data/mods/Aftershock/itemgroups/bionics_groups.json new file mode 100644 index 0000000000000..2fee362616910 --- /dev/null +++ b/data/mods/Aftershock/itemgroups/bionics_groups.json @@ -0,0 +1,44 @@ +[ + { + "id": "bionics", + "type": "item_group", + "items": [ + [ "bn_bio_solar", 10 ], + [ "afs_bio_wind_turbine", 5 ], + [ "afs_bio_missiles", 10 ], + [ "afs_bio_linguistic_coprocessor", 10 ], + [ "afs_bio_dopamine_stimulators", 10 ], + [ "bio_blaster", 5 ] + ] + }, + { + "id": "bionics_common", + "type": "item_group", + "items": [ [ "bn_bio_solar", 10 ], [ "afs_bio_wind_turbine", 5 ], [ "afs_bio_linguistic_coprocessor", 8 ] ] + }, + { + "id": "bionics_mil", + "type": "item_group", + "items": [ [ "bio_blaster", 5 ] ] + }, + { + "id": "bionics_sci", + "type": "item_group", + "items": [ [ "bn_bio_solar", 5 ], [ "afs_bio_wind_turbine", 2 ] ] + }, + { + "id": "bionics_op", + "type": "item_group", + "items": [ + [ "bn_bio_solar", 15 ], + [ "afs_bio_wind_turbine", 10 ], + [ "afs_bio_missiles", 10 ], + [ "afs_bio_dopamine_stimulators", 10 ] + ] + }, + { + "id": "bionics_subs", + "type": "item_group", + "items": [ [ "afs_bio_missiles", 10 ], [ "afs_bio_dopamine_stimulators", 15 ] ] + } +] diff --git a/data/mods/Aftershock/items/item_groups.json b/data/mods/Aftershock/itemgroups/item_groups.json similarity index 63% rename from data/mods/Aftershock/items/item_groups.json rename to data/mods/Aftershock/itemgroups/item_groups.json index e8b118bc87a82..5c4387a424d0b 100644 --- a/data/mods/Aftershock/items/item_groups.json +++ b/data/mods/Aftershock/itemgroups/item_groups.json @@ -1,4 +1,174 @@ [ + { + "id": "afs_weapons_rare", + "type": "item_group", + "items": [ + [ "emp_gun", 3 ], + [ "laser_rifle", 5 ], + [ "v29", 7 ], + [ "afs_hydraulic_gauntlet", 3 ], + [ "afs_energy_saber_off", 3 ], + [ "ftk93", 5 ], + [ "afs_hardlight_longbow", 2 ] + ] + }, + { + "id": "afs_lab_mechanics_books", + "type": "item_group", + "items": [ + [ "manual_mechanics", 6 ], + [ "textbook_mechanics", 3 ], + [ "textbook_biodiesel", 3 ], + [ "mag_fieldrepair", 4 ], + [ "book_icef", 4 ] + ] + }, + { + "id": "chem_lab", + "type": "item_group", + "items": [ [ "panacea", 1 ], [ "afs_calorie_pill", 5 ], [ "afs_sundew", 8 ] ] + }, + { + "id": "rare", + "type": "item_group", + "items": [ + [ "afs_calorie_pill", 10 ], + [ "afs_sundew", 10 ], + [ "afs_bag_of_holding", 1 ], + [ "afs_atomic_smartphone", 5 ], + [ "laser_pack", 10 ], + [ "ftk93", 5 ], + [ "atomic_butterchurn", 5 ] + ] + }, + { + "id": "spider", + "type": "item_group", + "items": [ [ "afs_energy_saber_off", 1 ], [ "afs_bag_of_holding", 2 ], [ "afs_hydraulic_gauntlet", 1 ] ] + }, + { + "id": "survivorzed_extra", + "type": "item_group", + "items": [ [ "afs_rolling_pin_barbed_wire", 5 ], [ "afs_chain_wrench", 8 ] ] + }, + { + "id": "camping", + "type": "item_group", + "items": [ [ "afs_rope_lighter", 10 ], [ "atomic_light", 1 ] ] + }, + { + "id": "allsporting", + "type": "item_group", + "items": [ [ "afs_rope_lighter", 10 ] ] + }, + { + "id": "traveler", + "type": "item_group", + "items": [ [ "afs_rope_lighter", 10 ] ] + }, + { + "id": "drugdealer", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 3 ], [ "afs_bio_missiles", 8 ] ] + }, + { + "id": "kitchen", + "type": "item_group", + "items": [ [ "afs_atompot", 1 ], [ "atomic_butterchurn", 1 ] ] + }, + { + "id": "oven", + "type": "item_group", + "items": [ [ "afs_atompot", 3 ] ] + }, + { + "id": "bed", + "type": "item_group", + "items": [ [ "afs_quilt", 10 ], [ "afs_quilt_patchwork", 8 ] ] + }, + { + "id": "livingroom", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] + }, + { + "id": "bedroom", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] + }, + { + "id": "consumer_electronics", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 2 ], [ "atomic_light", 4 ] ] + }, + { + "id": "electronics", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] + }, + { + "id": "lab_dorm", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 5 ], [ "atomic_light", 3 ] ] + }, + { + "id": "subway", + "type": "item_group", + "items": [ [ "afs_atomic_smartphone", 1 ] ] + }, + { + "id": "hardware", + "type": "item_group", + "items": [ [ "afs_power_cutter", 5 ], [ "atomic_butterchurn", 1 ] ] + }, + { + "id": "hardware_bulk", + "type": "item_group", + "//": "Not something you get in bulk, but it makes sense to be out in the back area", + "items": [ [ "afs_power_cutter", 1 ] ] + }, + { + "id": "mischw", + "type": "item_group", + "subtype": "collection", + "items": [ [ "afs_power_cutter", 5 ] ] + }, + { + "id": "book_gunref", + "type": "item_group", + "items": [ + [ "afs_textbook_shotguns", 3 ], + [ "afs_textbook_handguns", 3 ], + [ "afs_textbook_rifles", 3 ], + [ "afs_textbook_launchers", 3 ] + ] + }, + { + "id": "book_military", + "type": "item_group", + "items": [ + [ "afs_textbook_shotguns", 20 ], + [ "afs_textbook_handguns", 20 ], + [ "afs_textbook_rifles", 20 ], + [ "afs_textbook_launchers", 10 ] + ] + }, + { + "id": "textbooks", + "type": "item_group", + "items": [ + [ "afs_textbook_shotguns", 3 ], + [ "afs_textbook_handguns", 3 ], + [ "afs_textbook_rifles", 3 ], + [ "afs_textbook_launchers", 3 ], + [ "textbook_atomic", 8 ] + ] + }, + { + "id": "guns_pistol_improvised", + "type": "item_group", + "items": [ [ "v29_cheap", 10 ] ] + }, { "type": "item_group", "id": "afs_gardener_worn", @@ -104,98 +274,6 @@ [ "afs_neural_io_2", 15 ] ] }, - { - "id": "surgery", - "//": "extension of vanilla itemgroup", - "type": "item_group", - "items": [ [ "bionic_maintenance_toolkit", 20 ], [ "afs_biomaterial_4", 10 ], [ "afs_neural_io_3", 5 ] ] - }, - { - "id": "jewelry_accessories", - "type": "item_group", - "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_tooth", 35 ], [ "afs_titanium_ring", 35 ] ] - }, - { - "id": "rings_and_things", - "type": "item_group", - "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] - }, - { - "id": "jewelry_back", - "type": "item_group", - "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] - }, - { - "id": "jewelry_front", - "type": "item_group", - "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] - }, - { - "id": "weapons", - "type": "item_group", - "items": [ [ "afs_titanium_bat", 40 ] ] - }, - { - "id": "allsporting", - "type": "item_group", - "items": [ [ "afs_titanium_bat", 40 ] ] - }, - { - "id": "sports", - "type": "item_group", - "items": [ [ "afs_titanium_bat", 40 ] ] - }, - { - "id": "college_sports", - "type": "item_group", - "items": [ [ "afs_titanium_bat", 60 ] ] - }, - { - "id": "supplies_mechanics", - "type": "item_group", - "items": [ [ "afs_titanium_frame", 5 ] ] - }, - { - "id": "bikeshop_tools", - "type": "item_group", - "items": [ [ "afs_titanium_frame", 5 ] ] - }, - { - "type": "item_group", - "id": "steel_mill_foundry", - "items": [ [ "afs_titanium_small", 5 ], { "item": "afs_scrap_titanium", "prob": 5, "count": [ 1, 4 ] } ] - }, - { - "id": "oa_ig_rd_metal_trash", - "type": "item_group", - "items": [ [ "afs_titanium_frame", 5 ], { "item": "afs_scrap_titanium", "prob": 10, "count": [ 2, 8 ] } ] - }, - { - "id": "supplies_metal", - "type": "item_group", - "items": [ - { "item": "afs_titanium_frame", "prob": 5 }, - { "item": "afs_scrap_titanium", "prob": 5, "count": [ 2, 8 ] }, - [ "afs_titanium_small", 5 ] - ] - }, - { - "id": "clothing_watch", - "type": "item_group", - "items": [ { "item": "afs_titanium_watch", "prob": 50 } ] - }, - { - "id": "accessory_ring", - "type": "item_group", - "subtype": "distribution", - "items": [ { "item": "afs_titanium_ring", "prob": 50 } ] - }, - { - "id": "accessory_teeth", - "type": "item_group", - "subtype": "distribution", - "items": [ [ "afs_titanium_tooth", 25 ] ] - }, { "id": "swat_gear", "type": "item_group", @@ -254,29 +332,6 @@ "subtype": "collection", "items": [ [ "q_solarpack", 1 ] ] }, - { - "type": "item_group", - "id": "afs_scrapgroup", - "items": [ - [ "afs_biomaterial_1", 40 ], - [ "afs_biomaterial_2", 20 ], - [ "afs_biomaterial_3", 10 ], - [ "afs_biomaterial_4", 3 ], - [ "afs_circuitry_1", 25 ], - [ "afs_circuitry_2", 14 ], - [ "afs_circuitry_3", 6 ], - [ "afs_energy_storage_1", 30 ], - [ "afs_energy_storage_2", 19 ], - [ "afs_energy_storage_3", 2 ], - [ "afs_magnet_1", 18 ], - [ "afs_material_1", 100 ], - [ "afs_material_2", 40 ], - [ "afs_material_3", 20 ], - [ "afs_neural_io_1", 65 ], - [ "afs_neural_io_2", 10 ], - [ "plut_cell", 20 ] - ] - }, { "type": "item_group", "id": "exoticplants", diff --git a/data/mods/Aftershock/itemgroups/nuclear_reactor_groups.json b/data/mods/Aftershock/itemgroups/nuclear_reactor_groups.json new file mode 100644 index 0000000000000..f7d6375203b55 --- /dev/null +++ b/data/mods/Aftershock/itemgroups/nuclear_reactor_groups.json @@ -0,0 +1,31 @@ +[ + { + "id": "nuclear_waste", + "type": "item_group", + "subtype": "collection", + "entries": [ { "item": "nuclear_waste", "container-item": "hazardous_waste_drum", "charges": 10 } ] + }, + { + "id": "nuclear_reactor", + "type": "item_group", + "subtype": "collection", + "entries": [ + { "item": "nuclear_waste", "count-min": 5, "count-max": 10 }, + { "item": "nuclear_fuel", "count-min": 1, "count-max": 10 } + ] + }, + { + "id": "reactor_gear", + "type": "item_group", + "subtype": "collection", + "entries": [ + { "item": "hazmat_suit", "prob": 33 }, + { "item": "prussian_blue", "prob": 33 }, + { "item": "rad_monitor", "prob": 33 }, + { "item": "iodine", "prob": 33 }, + { "item": "flashlight", "prob": 33 }, + { "item": "1st_aid", "prob": 15 }, + { "item": "geiger_off", "prob": 15 } + ] + } +] diff --git a/data/mods/Aftershock/itemgroups/scrap_groups.json b/data/mods/Aftershock/itemgroups/scrap_groups.json new file mode 100644 index 0000000000000..293f81b734a66 --- /dev/null +++ b/data/mods/Aftershock/itemgroups/scrap_groups.json @@ -0,0 +1,30 @@ +[ + { + "id": "surgery", + "type": "item_group", + "items": [ [ "bionic_maintenance_toolkit", 20 ], [ "afs_biomaterial_4", 10 ], [ "afs_neural_io_3", 5 ] ] + }, + { + "type": "item_group", + "id": "afs_scrapgroup", + "items": [ + [ "afs_biomaterial_1", 40 ], + [ "afs_biomaterial_2", 20 ], + [ "afs_biomaterial_3", 10 ], + [ "afs_biomaterial_4", 3 ], + [ "afs_circuitry_1", 25 ], + [ "afs_circuitry_2", 14 ], + [ "afs_circuitry_3", 6 ], + [ "afs_energy_storage_1", 30 ], + [ "afs_energy_storage_2", 19 ], + [ "afs_energy_storage_3", 2 ], + [ "afs_magnet_1", 18 ], + [ "afs_material_1", 100 ], + [ "afs_material_2", 40 ], + [ "afs_material_3", 20 ], + [ "afs_neural_io_1", 65 ], + [ "afs_neural_io_2", 10 ], + [ "plut_cell", 20 ] + ] + } +] diff --git a/data/mods/Aftershock/itemgroups/titanium_groups.json b/data/mods/Aftershock/itemgroups/titanium_groups.json new file mode 100644 index 0000000000000..2fdbdb5687126 --- /dev/null +++ b/data/mods/Aftershock/itemgroups/titanium_groups.json @@ -0,0 +1,89 @@ +[ + { + "//": "extension of vanilla itemgroups, all adding titanium", + "id": "jewelry_accessories", + "type": "item_group", + "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_tooth", 35 ], [ "afs_titanium_ring", 35 ] ] + }, + { + "id": "rings_and_things", + "type": "item_group", + "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] + }, + { + "id": "jewelry_back", + "type": "item_group", + "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] + }, + { + "id": "jewelry_front", + "type": "item_group", + "items": [ [ "afs_titanium_watch", 35 ], [ "afs_titanium_ring", 35 ] ] + }, + { + "id": "weapons", + "type": "item_group", + "items": [ [ "afs_titanium_bat", 40 ] ] + }, + { + "id": "allsporting", + "type": "item_group", + "items": [ [ "afs_titanium_bat", 40 ] ] + }, + { + "id": "sports", + "type": "item_group", + "items": [ [ "afs_titanium_bat", 40 ] ] + }, + { + "id": "college_sports", + "type": "item_group", + "items": [ [ "afs_titanium_bat", 60 ] ] + }, + { + "id": "supplies_mechanics", + "type": "item_group", + "items": [ [ "afs_titanium_frame", 5 ] ] + }, + { + "id": "bikeshop_tools", + "type": "item_group", + "items": [ [ "afs_titanium_frame", 5 ] ] + }, + { + "type": "item_group", + "id": "steel_mill_foundry", + "items": [ [ "afs_titanium_small", 5 ], { "item": "afs_scrap_titanium", "prob": 5, "count": [ 1, 4 ] } ] + }, + { + "id": "oa_ig_rd_metal_trash", + "type": "item_group", + "items": [ [ "afs_titanium_frame", 5 ], { "item": "afs_scrap_titanium", "prob": 10, "count": [ 2, 8 ] } ] + }, + { + "id": "supplies_metal", + "type": "item_group", + "items": [ + { "item": "afs_titanium_frame", "prob": 5 }, + { "item": "afs_scrap_titanium", "prob": 5, "count": [ 2, 8 ] }, + [ "afs_titanium_small", 5 ] + ] + }, + { + "id": "clothing_watch", + "type": "item_group", + "items": [ { "item": "afs_titanium_watch", "prob": 50 } ] + }, + { + "id": "accessory_ring", + "type": "item_group", + "subtype": "distribution", + "items": [ { "item": "afs_titanium_ring", "prob": 50 } ] + }, + { + "id": "accessory_teeth", + "type": "item_group", + "subtype": "distribution", + "items": [ [ "afs_titanium_tooth", 25 ] ] + } +] diff --git a/data/mods/Aftershock/items/monster_drops.json b/data/mods/Aftershock/items/monster_drops.json deleted file mode 100644 index 23b6f3084a857..0000000000000 --- a/data/mods/Aftershock/items/monster_drops.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "item_group", - "subtype": "collection", - "id": "mon_afs_sentinel_lx_drops", - "entries": [ - { "item": "afs_sentinel_cloak" } - ] -} diff --git a/data/mods/Aftershock/maps/item_groups.json b/data/mods/Aftershock/maps/item_groups.json deleted file mode 100644 index e1ac01ca46cdc..0000000000000 --- a/data/mods/Aftershock/maps/item_groups.json +++ /dev/null @@ -1,243 +0,0 @@ -[ - { - "id": "afs_weapons_rare", - "type": "item_group", - "items": [ - [ "emp_gun", 3 ], - [ "laser_rifle", 5 ], - [ "v29", 7 ], - [ "afs_hydraulic_gauntlet", 3 ], - [ "afs_energy_saber_off", 3 ], - [ "ftk93", 5 ], - [ "afs_hardlight_longbow", 2 ] - ] - }, - { - "id": "afs_lab_mechanics_books", - "type": "item_group", - "items": [ - [ "manual_mechanics", 6 ], - [ "textbook_mechanics", 3 ], - [ "textbook_biodiesel", 3 ], - [ "mag_fieldrepair", 4 ], - [ "book_icef", 4 ] - ] - }, - { - "id": "bionics", - "type": "item_group", - "items": [ - [ "bn_bio_solar", 10 ], - [ "afs_bio_wind_turbine", 5 ], - [ "afs_bio_missiles", 10 ], - [ "afs_bio_linguistic_coprocessor", 10 ], - [ "afs_bio_dopamine_stimulators", 10 ], - [ "bio_blaster", 5 ] - ] - }, - { - "id": "bionics_common", - "type": "item_group", - "items": [ [ "bn_bio_solar", 10 ], [ "afs_bio_wind_turbine", 5 ], [ "afs_bio_linguistic_coprocessor", 8 ] ] - }, - { - "id": "bionics_mil", - "type": "item_group", - "items": [ [ "bio_blaster", 5 ] ] - }, - { - "id": "bionics_sci", - "type": "item_group", - "items": [ [ "bn_bio_solar", 5 ], [ "afs_bio_wind_turbine", 2 ] ] - }, - { - "id": "bionics_op", - "type": "item_group", - "items": [ - [ "bn_bio_solar", 15 ], - [ "afs_bio_wind_turbine", 10 ], - [ "afs_bio_missiles", 10 ], - [ "afs_bio_dopamine_stimulators", 10 ] - ] - }, - { - "id": "bionics_subs", - "type": "item_group", - "items": [ [ "afs_bio_missiles", 10 ], [ "afs_bio_dopamine_stimulators", 15 ] ] - }, - { - "id": "chem_lab", - "type": "item_group", - "items": [ [ "panacea", 1 ], [ "afs_calorie_pill", 5 ], [ "afs_sundew", 8 ] ] - }, - { - "id": "rare", - "type": "item_group", - "items": [ - [ "afs_calorie_pill", 10 ], - [ "afs_sundew", 10 ], - [ "afs_bag_of_holding", 1 ], - [ "afs_atomic_smartphone", 5 ], - [ "laser_pack", 10 ], - [ "ftk93", 5 ], - [ "atomic_butterchurn", 5 ] - ] - }, - { - "id": "spider", - "type": "item_group", - "items": [ [ "afs_energy_saber_off", 1 ], [ "afs_bag_of_holding", 2 ], [ "afs_hydraulic_gauntlet", 1 ] ] - }, - { - "id": "survivorzed_extra", - "type": "item_group", - "items": [ [ "afs_rolling_pin_barbed_wire", 5 ], [ "afs_chain_wrench", 8 ] ] - }, - { - "id": "camping", - "type": "item_group", - "items": [ [ "afs_rope_lighter", 10 ], [ "atomic_light", 1 ] ] - }, - { - "id": "allsporting", - "type": "item_group", - "items": [ [ "afs_rope_lighter", 10 ] ] - }, - { - "id": "traveler", - "type": "item_group", - "items": [ [ "afs_rope_lighter", 10 ] ] - }, - { - "id": "drugdealer", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 3 ], [ "afs_bio_missiles", 8 ] ] - }, - { - "id": "kitchen", - "type": "item_group", - "items": [ [ "afs_atompot", 1 ], [ "atomic_butterchurn", 1 ] ] - }, - { - "id": "oven", - "type": "item_group", - "items": [ [ "afs_atompot", 3 ] ] - }, - { - "id": "bed", - "type": "item_group", - "items": [ [ "afs_quilt", 10 ], [ "afs_quilt_patchwork", 8 ] ] - }, - { - "id": "livingroom", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] - }, - { - "id": "bedroom", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] - }, - { - "id": "consumer_electronics", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 2 ], [ "atomic_light", 4 ] ] - }, - { - "id": "electronics", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 1 ], [ "atomic_light", 2 ] ] - }, - { - "id": "lab_dorm", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 5 ], [ "atomic_light", 3 ] ] - }, - { - "id": "subway", - "type": "item_group", - "items": [ [ "afs_atomic_smartphone", 1 ] ] - }, - { - "id": "hardware", - "type": "item_group", - "items": [ [ "afs_power_cutter", 5 ], [ "atomic_butterchurn", 1 ] ] - }, - { - "id": "hardware_bulk", - "type": "item_group", - "//": "Not something you get in bulk, but it makes sense to be out in the back area", - "items": [ [ "afs_power_cutter", 1 ] ] - }, - { - "id": "mischw", - "type": "item_group", - "subtype": "collection", - "items": [ [ "afs_power_cutter", 5 ] ] - }, - { - "id": "book_gunref", - "type": "item_group", - "items": [ - [ "afs_textbook_shotguns", 3 ], - [ "afs_textbook_handguns", 3 ], - [ "afs_textbook_rifles", 3 ], - [ "afs_textbook_launchers", 3 ] - ] - }, - { - "id": "book_military", - "type": "item_group", - "items": [ - [ "afs_textbook_shotguns", 20 ], - [ "afs_textbook_handguns", 20 ], - [ "afs_textbook_rifles", 20 ], - [ "afs_textbook_launchers", 10 ] - ] - }, - { - "id": "textbooks", - "type": "item_group", - "items": [ - [ "afs_textbook_shotguns", 3 ], - [ "afs_textbook_handguns", 3 ], - [ "afs_textbook_rifles", 3 ], - [ "afs_textbook_launchers", 3 ], - [ "textbook_atomic", 8 ] - ] - }, - { - "id": "guns_pistol_improvised", - "type": "item_group", - "items": [ [ "v29_cheap", 10 ] ] - }, - { - "id": "nuclear_waste", - "type": "item_group", - "subtype": "collection", - "entries": [ { "item": "nuclear_waste", "container-item": "hazardous_waste_drum", "charges": 10 } ] - }, - { - "id": "nuclear_reactor", - "type": "item_group", - "subtype": "collection", - "entries": [ - { "item": "nuclear_waste", "count-min": 5, "count-max": 10 }, - { "item": "nuclear_fuel", "count-min": 1, "count-max": 10 } - ] - }, - { - "id": "reactor_gear", - "type": "item_group", - "subtype": "collection", - "entries": [ - { "item": "hazmat_suit", "prob": 33 }, - { "item": "prussian_blue", "prob": 33 }, - { "item": "rad_monitor", "prob": 33 }, - { "item": "iodine", "prob": 33 }, - { "item": "flashlight", "prob": 33 }, - { "item": "1st_aid", "prob": 15 }, - { "item": "geiger_off", "prob": 15 } - ] - } -] diff --git a/data/mods/Aftershock/items/monsterdrops.json b/data/mods/Aftershock/monsterdrops/monsterdrops.json similarity index 93% rename from data/mods/Aftershock/items/monsterdrops.json rename to data/mods/Aftershock/monsterdrops/monsterdrops.json index ac52557be4859..29c72ce088d0a 100644 --- a/data/mods/Aftershock/items/monsterdrops.json +++ b/data/mods/Aftershock/monsterdrops/monsterdrops.json @@ -1,4 +1,10 @@ [ + { + "type": "item_group", + "subtype": "collection", + "id": "mon_afs_sentinel_lx_drops", + "entries": [ { "item": "afs_sentinel_cloak" } ] + }, { "type": "item_group", "id": "tripod", From dc8519d40a1a40a2d543cf501c678cec3798ad61 Mon Sep 17 00:00:00 2001 From: martinrhan <53336429+martinrhan@users.noreply.github.com> Date: Sun, 28 Jun 2020 03:34:00 +0800 Subject: [PATCH 04/41] Fire spell ignite things (#41108) * Update magic_spell_effect.cpp * Update magic_spell_effect.cpp * Update magic.h * Update kelvinist.json * Update monsterspells.json * Update kelvinist.json * Update magic_spell_effect.cpp * Update monsterspells.json * Update monsterspells.json * edit as reqiured * Update magic_spell_effect.cpp * Update src/magic_spell_effect.cpp Co-authored-by: BevapDin Co-authored-by: BevapDin --- data/mods/Magiclysm/Spells/kelvinist.json | 4 ++-- data/mods/Magiclysm/Spells/monsterspells.json | 1 + src/magic.cpp | 1 + src/magic.h | 1 + src/magic_spell_effect.cpp | 3 +++ 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/data/mods/Magiclysm/Spells/kelvinist.json b/data/mods/Magiclysm/Spells/kelvinist.json index 9d6accf1b4be4..db7d093729da0 100644 --- a/data/mods/Magiclysm/Spells/kelvinist.json +++ b/data/mods/Magiclysm/Spells/kelvinist.json @@ -73,7 +73,7 @@ "description": "You hurl a pea-sized glowing orb that when reaches its target or an obstacle produces a pressure-less blast of searing heat.", "effect": "projectile_attack", "valid_targets": [ "self", "ally", "hostile", "ground" ], - "flags": [ "SOMATIC", "VERBAL", "NO_LEGS" ], + "flags": [ "SOMATIC", "VERBAL", "NO_LEGS", "IGNITE_FLAMMABLE" ], "max_level": 20, "min_damage": 24, "max_damage": 68, @@ -127,7 +127,7 @@ "description": "You're pretty sure you saw this in a game somewhere. You fire a short-range cone of fire.", "effect": "cone_attack", "valid_targets": [ "ally", "hostile", "ground" ], - "flags": [ "SOMATIC", "VERBAL" ], + "flags": [ "SOMATIC", "VERBAL", "IGNITE_FLAMMABLE" ], "max_level": 20, "min_damage": 8, "max_damage": 65, diff --git a/data/mods/Magiclysm/Spells/monsterspells.json b/data/mods/Magiclysm/Spells/monsterspells.json index f9e5eab85b216..f38aef607981e 100644 --- a/data/mods/Magiclysm/Spells/monsterspells.json +++ b/data/mods/Magiclysm/Spells/monsterspells.json @@ -83,6 +83,7 @@ "id": "mon_demon_fireball", "name": "Demon Fireball", "description": "This is a monster only spell.", + "flags": [ "IGNITE_FLAMMABLE" ], "valid_targets": [ "hostile", "ground", "ally", "self" ], "min_damage": 15, "max_damage": 15, diff --git a/src/magic.cpp b/src/magic.cpp index c4a81e6892421..d2ce42e5530f1 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -118,6 +118,7 @@ std::string enum_to_string( spell_flag data ) case spell_flag::PAIN_NORESIST: return "PAIN_NORESIST"; case spell_flag::WITH_CONTAINER: return "WITH_CONTAINER"; case spell_flag::SPAWN_GROUP: return "SPAWN_GROUP"; + case spell_flag::IGNITE_FLAMMABLE: return "IGNITE_FLAMMABLE"; case spell_flag::NO_FAIL: return "NO_FAIL"; case spell_flag::WONDER: return "WONDER"; case spell_flag::LAST: break; diff --git a/src/magic.h b/src/magic.h index 2f658c002889e..69a6fabf55c43 100644 --- a/src/magic.h +++ b/src/magic.h @@ -59,6 +59,7 @@ enum class spell_flag : int { NO_FAIL, // this spell cannot fail when you cast it WITH_CONTAINER, // items spawned with container SPAWN_GROUP, // spawn or summon from an item or monster group, instead of individual item/monster ID + IGNITE_FLAMMABLE, // if spell effect area has any thing flamable, a fire will be produced LAST }; diff --git a/src/magic_spell_effect.cpp b/src/magic_spell_effect.cpp index aa6739370a8f2..8b2fb636c9301 100644 --- a/src/magic_spell_effect.cpp +++ b/src/magic_spell_effect.cpp @@ -422,6 +422,9 @@ static void damage_targets( const spell &sp, Creature &caster, } sp.make_sound( target ); sp.create_field( target ); + if( sp.has_flag( spell_flag::IGNITE_FLAMMABLE ) && g->m.is_flammable( target ) ) { + g->m.add_field( target, fd_fire, 1, 10_minutes ); + } Creature *const cr = g->critter_at( target ); if( !cr ) { continue; From 2ac73d3755f6298e82ad85d8b40e8c219517cfd2 Mon Sep 17 00:00:00 2001 From: nexusmrsep Date: Sat, 27 Jun 2020 21:46:24 +0200 Subject: [PATCH 05/41] fix gas tanks spawning without charges --- data/json/items/tool/med.json | 7 ++++++- data/json/items/tool_armor.json | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/data/json/items/tool/med.json b/data/json/items/tool/med.json index c0db5ebb543c8..400eab10eaac0 100644 --- a/data/json/items/tool/med.json +++ b/data/json/items/tool/med.json @@ -126,6 +126,9 @@ "symbol": ";", "color": "light_gray", "initial_charges": 12, + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "watertight": true, "rigid": true, "ammo_restriction": { "oxygen": 12 } } + ], "max_charges": 12, "charges_per_use": 1, "use_action": [ "OXYGEN_BOTTLE" ] @@ -175,7 +178,9 @@ "symbol": ";", "color": "light_gray", "initial_charges": 24, - "pocket_data": [ { "pocket_type": "MAGAZINE", "airtight": true, "watertight": true, "ammo_restriction": { "oxygen": 24 } } ], + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "watertight": true, "rigid": true, "ammo_restriction": { "oxygen": 24 } } + ], "max_charges": 24, "charges_per_use": 1, "use_action": [ "OXYGEN_BOTTLE" ] diff --git a/data/json/items/tool_armor.json b/data/json/items/tool_armor.json index b5c89e26b1e6a..a0a718705bb39 100644 --- a/data/json/items/tool_armor.json +++ b/data/json/items/tool_armor.json @@ -2981,7 +2981,9 @@ "color": "light_gray", "initial_charges": 60, "ammo": "nitrox", - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "nitrox": 60 } } ], + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "rigid": true, "watertight": true, "ammo_restriction": { "nitrox": 60 } } + ], "covers": [ "TORSO" ], "flags": [ "WATER_FRIENDLY", "BELTED", "ONLY_ONE", "STURDY", "NO_UNLOAD" ], "environmental_protection": 1, @@ -3009,7 +3011,9 @@ "symbol": ";", "color": "light_gray", "ammo": "nitrox", - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "nitrox": 60 } } ], + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "rigid": true, "watertight": true, "ammo_restriction": { "nitrox": 60 } } + ], "charges_per_use": 1, "turns_per_charge": 60, "covers": [ "TORSO", "MOUTH" ], @@ -3038,7 +3042,9 @@ "symbol": ";", "color": "light_gray", "ammo": "nitrox", - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "nitrox": 20 } } ], + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "rigid": true, "watertight": true, "ammo_restriction": { "nitrox": 20 } } + ], "max_charges": 20, "covers": [ "TORSO" ], "flags": [ "WATER_FRIENDLY", "BELTED", "ONLY_ONE", "STURDY", "NO_UNLOAD" ], @@ -3067,7 +3073,9 @@ "symbol": ";", "color": "light_gray", "ammo": "nitrox", - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "nitrox": 20 } } ], + "pocket_data": [ + { "pocket_type": "MAGAZINE", "airtight": true, "rigid": true, "watertight": true, "ammo_restriction": { "nitrox": 20 } } + ], "charges_per_use": 1, "turns_per_charge": 60, "covers": [ "TORSO", "MOUTH" ], From e061dbb2c1a0c35bcb1eae2f3a8a07f62e26370e Mon Sep 17 00:00:00 2001 From: John Candlebury Date: Sat, 27 Jun 2020 21:27:18 -0600 Subject: [PATCH 06/41] Add Polymorph Spells (#41466) * c++ support for polymorph spells * Debug random polymorph spell * Magus Baleful Polymorph * Animist Soul Rend * Remove duplicated declaration How did that ever happen? * Better description for Runic Tablet * Remove unused variables * Update src/magic.cpp Co-authored-by: BevapDin * Apply suggestions from code review Co-authored-by: BevapDin * Code correction based on reviews * Fix typo on frog's description * Style code * Update data/mods/Magiclysm/Spells/debug.json * Cant polymorph into halucinations/generators. * Use Static Variable to check for "mon_generator" Co-authored-by: BevapDin Co-authored-by: Curtis Merrill --- data/mods/Magiclysm/Spells/animist.json | 24 +++++++ data/mods/Magiclysm/Spells/debug.json | 19 +++++ data/mods/Magiclysm/Spells/magus.json | 23 +++++++ .../mods/Magiclysm/itemgroups/spellbooks.json | 2 + data/mods/Magiclysm/items/spell_scrolls.json | 9 +++ data/mods/Magiclysm/items/spellbooks.json | 13 ++++ data/mods/Magiclysm/monstergroups.json | 10 +++ data/mods/Magiclysm/monsters/monsters.json | 22 ++++++ src/creature.h | 6 ++ src/magic.cpp | 21 ++++++ src/magic.h | 4 ++ src/magic_spell_effect.cpp | 69 +++++++++++++++++++ src/monster.h | 7 ++ 13 files changed, 229 insertions(+) diff --git a/data/mods/Magiclysm/Spells/animist.json b/data/mods/Magiclysm/Spells/animist.json index d437e715b6483..2433112624798 100644 --- a/data/mods/Magiclysm/Spells/animist.json +++ b/data/mods/Magiclysm/Spells/animist.json @@ -187,6 +187,30 @@ "energy_source": "MANA", "flags": [ "PERMANENT", "NO_LEGS", "CONCENTRATE" ] }, + { + "id": "soulrend", + "type": "SPELL", + "name": "Soulrend", + "description": "Violently tears the spirit from the body, and bounds the resulting shade to your will.", + "valid_targets": [ "hostile", "ally" ], + "flags": [ "NO_LEGS", "LOUD", "SOMATIC", "POLYMORPH_GROUP", "FRIENDLY_POLY" ], + "effect": "targeted_polymorph", + "effect_str": "GROUP_POLYMORPH_SHADOW", + "spell_class": "ANIMIST", + "energy_source": "MANA", + "difficulty": 15, + "min_damage": 40, + "max_damage": 140, + "damage_increment": 2.5, + "max_level": 40, + "base_casting_time": 200, + "casting_time_increment": -2.0, + "final_casting_time": 120, + "base_energy_cost": 200, + "min_range": 5, + "max_range": 30, + "range_increment": 1.0 + }, { "id": "summon_wisps", "type": "SPELL", diff --git a/data/mods/Magiclysm/Spells/debug.json b/data/mods/Magiclysm/Spells/debug.json index 00ae21011c60e..f8bb3733743a9 100644 --- a/data/mods/Magiclysm/Spells/debug.json +++ b/data/mods/Magiclysm/Spells/debug.json @@ -89,6 +89,25 @@ "base_energy_cost": 100, "energy_source": "FATIGUE" }, + { + "id": "debug_polymorph", + "type": "SPELL", + "name": "Debug polymorph", + "description": "Well you wanted to lose weight, right?", + "valid_targets": [ "hostile", "ally" ], + "flags": [ "NO_LEGS", "LOUD", "SOMATIC" ], + "effect": "targeted_polymorph", + "energy_source": "MANA", + "difficulty": 1, + "min_damage": 9999, + "max_damage": 9999, + "max_level": 1, + "base_casting_time": 10, + "base_energy_cost": 1, + "final_energy_cost": 1, + "min_range": 30, + "max_range": 30 + }, { "id": "debug_hp", "type": "SPELL", diff --git a/data/mods/Magiclysm/Spells/magus.json b/data/mods/Magiclysm/Spells/magus.json index f6d54d304ffb7..70d3f2d7e95a3 100644 --- a/data/mods/Magiclysm/Spells/magus.json +++ b/data/mods/Magiclysm/Spells/magus.json @@ -133,6 +133,29 @@ "max_duration": 12000, "duration_increment": 600 }, + { + "id": "magus_baleful_polymorph", + "type": "SPELL", + "name": "Baleful Polymorph", + "description": "Transform your enemies into frogs.", + "valid_targets": [ "hostile" ], + "flags": [ "VERBAL", "SOMATIC", "NO_LEGS" ], + "effect": "targeted_polymorph", + "effect_str": "mon_baleful_polymorph_frog", + "spell_class": "MAGUS", + "energy_source": "MANA", + "base_casting_time": 150, + "base_energy_cost": 150, + "difficulty": 8, + "max_level": 20, + "min_damage": 20, + "max_damage": 40, + "damage_increment": 2, + "damage_type": "none", + "min_range": 5, + "max_range": 30, + "range_increment": 1.5 + }, { "id": "magus_mana_beam", "type": "SPELL", diff --git a/data/mods/Magiclysm/itemgroups/spellbooks.json b/data/mods/Magiclysm/itemgroups/spellbooks.json index d4bc49915a91d..3806b2c6bef61 100644 --- a/data/mods/Magiclysm/itemgroups/spellbooks.json +++ b/data/mods/Magiclysm/itemgroups/spellbooks.json @@ -87,6 +87,7 @@ [ "spell_scroll_vicious_tentacle", 40 ], [ "spell_scroll_bio_bonespear", 20 ], [ "spell_scroll_megablast", 10 ], + [ "spell_scroll_baleful_polymorph", 20 ], [ "spell_scroll_eshaper_shardstorm", 50 ], [ "spell_scroll_fireball", 50 ], [ "spell_scroll_cone_cold", 50 ], @@ -153,6 +154,7 @@ "id": "spellbook_tier_3", "type": "item_group", "items": [ + [ "animist_shadows", 5 ], [ "magus_spellbook", 15 ], [ "magus_spellbook_move", 30 ], [ "translocate_spellbook", 20 ], diff --git a/data/mods/Magiclysm/items/spell_scrolls.json b/data/mods/Magiclysm/items/spell_scrolls.json index b929312195135..a688d765d5743 100644 --- a/data/mods/Magiclysm/items/spell_scrolls.json +++ b/data/mods/Magiclysm/items/spell_scrolls.json @@ -82,6 +82,15 @@ "description": "With an intense ritual that resembles crossfit, you manage to put some of your pain at bay.", "use_action": { "type": "learn_spell", "spells": [ "recover_pain" ] } }, + { + "type": "BOOK", + "copy-from": "spell_scroll", + "id": "spell_scroll_baleful_polymorph", + "//": "Technomancer spell", + "name": { "str": "Scroll of Baleful Polymorph", "str_pl": "Scrolls of Baleful Polymorph" }, + "description": "Transform your enemies into frogs.", + "use_action": { "type": "learn_spell", "spells": [ "magus_baleful_polymorph" ] } + }, { "type": "BOOK", "copy-from": "spell_scroll", diff --git a/data/mods/Magiclysm/items/spellbooks.json b/data/mods/Magiclysm/items/spellbooks.json index 248c3de9a628b..121c4a3fa3cbd 100644 --- a/data/mods/Magiclysm/items/spellbooks.json +++ b/data/mods/Magiclysm/items/spellbooks.json @@ -338,6 +338,19 @@ "color": "light_gray", "use_action": { "type": "learn_spell", "spells": [ "taze", "laze" ] } }, + { + "id": "animist_shadows", + "type": "BOOK", + "name": { "str": "Runic Tablet shard" }, + "//": "1 classless spell", + "description": "A small tablet of blackened stone, apparently cut from a much larger slab. Golden runes glow over its surface, and slowly shift into intelligible sentences when you stare at them.", + "weight": "4000 g", + "volume": "2500 ml", + "material": [ "stone" ], + "symbol": "?", + "color": "light_gray", + "use_action": { "type": "learn_spell", "spells": [ "soulrend" ] } + }, { "id": "translocate_spellbook", "type": "BOOK", diff --git a/data/mods/Magiclysm/monstergroups.json b/data/mods/Magiclysm/monstergroups.json index c9636e361e5af..9fcfdc9297c13 100644 --- a/data/mods/Magiclysm/monstergroups.json +++ b/data/mods/Magiclysm/monstergroups.json @@ -45,6 +45,16 @@ { "monster": "mon_lemure", "freq": 5, "cost_multiplier": 2, "pack_size": [ 1, 4 ] } ] }, + { + "type": "monstergroup", + "name": "GROUP_POLYMORPH_SHADOW", + "default": "mon_shadow", + "is_animal": true, + "monsters": [ + { "monster": "mon_shadow", "freq": 100, "cost_multiplier": 1 }, + { "monster": "mon_shadow_snake", "freq": 10, "cost_multiplier": 1 } + ] + }, { "type": "monstergroup", "name": "GROUP_WORM", diff --git a/data/mods/Magiclysm/monsters/monsters.json b/data/mods/Magiclysm/monsters/monsters.json index de043cea2e404..cb98c88e4abd0 100644 --- a/data/mods/Magiclysm/monsters/monsters.json +++ b/data/mods/Magiclysm/monsters/monsters.json @@ -307,6 +307,28 @@ "death_function": [ "NORMAL" ], "flags": [ "SEES", "NOHEAD", "POISON", "IMMOBILE", "NO_BREATHE", "PACIFIST" ] }, + { + "id": "mon_baleful_polymorph_frog", + "type": "MONSTER", + "name": { "str": "frog" }, + "description": "A conspicuously average american bullfrog. You better keep prince charming away from it.", + "default_faction": "magical_beast", + "species": [ "AMPHIBIAN" ], + "volume": "750 ml", + "weight": "1 kg", + "hp": 3, + "speed": 80, + "material": [ "flesh" ], + "symbol": "b", + "color": "green", + "melee_cut": 0, + "dodge": 6, + "harvest": "mammal_tiny", + "special_attacks": [ { "type": "leap", "cooldown": 10, "max_range": 5 } ], + "fear_triggers": [ "PLAYER_CLOSE" ], + "death_function": [ "NORMAL" ], + "flags": [ "SEES", "SMELLS", "HEARS", "SWIMS" ] + }, { "id": "mon_lemure", "type": "MONSTER", diff --git a/src/creature.h b/src/creature.h index e6d22a3a57fc0..be16c662cfc7a 100644 --- a/src/creature.h +++ b/src/creature.h @@ -242,6 +242,12 @@ class Creature virtual const avatar *as_avatar() const { return nullptr; } + virtual monster *as_monster() { + return nullptr; + } + virtual const monster *as_monster() const { + return nullptr; + } /** return the direction the creature is facing, for sdl horizontal flip **/ FacingDirection facing = FacingDirection::RIGHT; /** Returns true for non-real Creatures used temporarily; i.e. fake NPC's used for turret fire. */ diff --git a/src/magic.cpp b/src/magic.cpp index d2ce42e5530f1..116f265e473ee 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -101,6 +101,8 @@ std::string enum_to_string( spell_flag data ) case spell_flag::IGNORE_WALLS: return "IGNORE_WALLS"; case spell_flag::HOSTILE_SUMMON: return "HOSTILE_SUMMON"; case spell_flag::HOSTILE_50: return "HOSTILE_50"; + case spell_flag::FRIENDLY_POLY: return "FRIENDLY_POLY"; + case spell_flag::POLYMORPH_GROUP: return "POLYMORPH_GROUP"; case spell_flag::SILENT: return "SILENT"; case spell_flag::LOUD: return "LOUD"; case spell_flag::VERBAL: return "VERBAL"; @@ -219,6 +221,7 @@ void spell_type::load( const JsonObject &jo, const std::string & ) effect_map{ { "pain_split", spell_effect::pain_split }, { "target_attack", spell_effect::target_attack }, + { "targeted_polymorph", spell_effect::targeted_polymorph }, { "projectile_attack", spell_effect::projectile_attack }, { "cone_attack", spell_effect::cone_attack }, { "line_attack", spell_effect::line_attack }, @@ -1790,6 +1793,22 @@ void spellcasting_callback::draw_spell_info( const spell &sp, const uilist *menu } damage_string = string_format( "%s %d %s", _( "Summon" ), sp.damage(), _( monster_name ) ); aoe_string = string_format( "%s: %d", _( "Spell Radius" ), sp.aoe() ); + } else if( fx == "targeted_polymorph" ) { + std::string monster_name = sp.effect_data(); + if( sp.has_flag( spell_flag::POLYMORPH_GROUP ) ) { + // TODO: Get a more user-friendly group name + if( MonsterGroupManager::isValidMonsterGroup( mongroup_id( sp.effect_data() ) ) ) { + monster_name = _( "random creature" ); + } else { + debugmsg( "Unknown monster group: %s", sp.effect_data() ); + } + } else if( monster_name.empty() ) { + monster_name = _( "random creature" ); + } else { + monster_name = mtype_id( sp.effect_data() )->nname(); + } + damage_string = string_format( _( "Targets under: %dhp become a %s" ), sp.damage(), + monster_name ); } else if( fx == "ter_transform" ) { aoe_string = string_format( "%s: %s", _( "Spell Radius" ), sp.aoe_string() ); } @@ -1982,6 +2001,8 @@ static void draw_spellbook_info( const spell_type &sp, uilist *menu ) has_damage_type = sp.min_damage > 0 && sp.max_damage > 0; } else if( fx == "spawn_item" || fx == "summon_monster" ) { damage_string = _( "Spawned" ); + } else if( fx == "targeted_polymorph" ) { + damage_string = _( "Threshold" ); } else if( fx == "recover_energy" ) { damage_string = _( "Recover" ); } else if( fx == "teleport_random" ) { diff --git a/src/magic.h b/src/magic.h index 69a6fabf55c43..a46ad99c80cce 100644 --- a/src/magic.h +++ b/src/magic.h @@ -41,6 +41,8 @@ enum class spell_flag : int { SWAP_POS, // a projectile spell swaps the positions of the caster and target HOSTILE_SUMMON, // summon spell always spawns a hostile monster HOSTILE_50, // summoned monster spawns friendly 50% of the time + POLYMORPH_GROUP, // polymorph spell chooses a monster from a group + FRIENDLY_POLY, // polymorph spell makes the monster friendly SILENT, // spell makes no noise at target LOUD, // spell makes extra noise at target VERBAL, // spell makes noise at caster location, mouth encumbrance affects fail % @@ -518,6 +520,8 @@ void teleport_random( const spell &sp, Creature &caster, const tripoint & ); void pain_split( const spell &, Creature &, const tripoint & ); void target_attack( const spell &sp, Creature &caster, const tripoint &epicenter ); +void targeted_polymorph( const spell &sp, Creature &caster, const tripoint &target ); + void projectile_attack( const spell &sp, Creature &caster, const tripoint &target ); void cone_attack( const spell &sp, Creature &caster, diff --git a/src/magic_spell_effect.cpp b/src/magic_spell_effect.cpp index 8b2fb636c9301..f3aed9077037f 100644 --- a/src/magic_spell_effect.cpp +++ b/src/magic_spell_effect.cpp @@ -32,6 +32,7 @@ #include "magic_spell_effect_helpers.h" #include "magic_teleporter_list.h" #include "magic_ter_furn_transform.h" +#include "monstergenerator.h" #include "map.h" #include "map_iterator.h" #include "messages.h" @@ -52,6 +53,8 @@ #include "vehicle.h" #include "vpart_position.h" +static const mtype_id mon_generator( "mon_generator" ); + namespace spell_detail { struct line_iterable { @@ -481,6 +484,72 @@ void spell_effect::target_attack( const spell &sp, Creature &caster, } } +static void magical_polymorph( monster &victim, Creature &caster, const spell &sp ) +{ + mtype_id new_id = mtype_id( sp.effect_data() ); + + if( sp.has_flag( spell_flag::POLYMORPH_GROUP ) ) { + const mongroup_id group_id( sp.effect_data() ); + new_id = MonsterGroupManager::GetRandomMonsterFromGroup( group_id ); + } + + // if effect_str is empty, we become a random monster of close difficulty + if( new_id.is_empty() ) { + int victim_diff = victim.type->difficulty; + const std::vector &mtypes = MonsterGenerator::generator().get_all_mtypes(); + for( int difficulty_variance = 1; difficulty_variance < 2048; difficulty_variance *= 2 ) { + unsigned int random_entry = rng( 0, mtypes.size() ); + unsigned int iter = random_entry + 1; + while( iter != random_entry && new_id.is_empty() ) { + if( iter >= mtypes.size() ) { + iter = 0; + } + if( ( mtypes[iter].id != victim.type->id ) && ( std::abs( mtypes[iter].difficulty - victim_diff ) + <= difficulty_variance ) ) { + if( !mtypes[iter].in_species( species_id( "HALLUCINATION" ) ) && + mtypes[iter].id != mon_generator ) { + new_id = mtypes[iter].id; + break; + } + } + iter++; + } + } + } + + if( !new_id.is_valid() ) { + debugmsg( "magical_polymorph called with an invalid monster id" ); + return; + } + + if( g->u.sees( victim ) ) { + add_msg( _( "The %s transforms into a %s." ), victim.type->nname(), + new_id->nname() ); + } + victim.poly( new_id ); + + if( sp.has_flag( spell_flag::FRIENDLY_POLY ) ) { + if( caster.as_player() ) { + victim.friendly = -1; + } else { + victim.make_ally( *caster.as_monster() ); + } + } +} + +void spell_effect::targeted_polymorph( const spell &sp, Creature &caster, const tripoint &target ) +{ + //we only target monsters for now. + if( monster *const victim = g->critter_at( target ) ) { + if( victim->get_hp() < sp.damage() ) { + magical_polymorph( *victim, caster, sp ); + return; + } + } + //victim had high hp, or isn't a monster. + caster.add_msg_if_player( m_bad, _( "Your target resists transformation." ) ); +} + void spell_effect::cone_attack( const spell &sp, Creature &caster, const tripoint &target ) { diff --git a/src/monster.h b/src/monster.h index 8bb35fbb54f3c..d4e71015b717f 100644 --- a/src/monster.h +++ b/src/monster.h @@ -95,6 +95,13 @@ class monster : public Creature bool is_monster() const override { return true; } + monster *as_monster() override { + return this; + } + const monster *as_monster() const override { + return this; + } + void poly( const mtype_id &id ); bool can_upgrade(); From f7d8d2d95feacd5960b100460a0745bfab120ddf Mon Sep 17 00:00:00 2001 From: anothersimulacrum <42699974+anothersimulacrum@users.noreply.github.com> Date: Sat, 27 Jun 2020 21:01:51 -0700 Subject: [PATCH 07/41] Fix crash on reviving zombie before game starts When corpses were placed during mapgen for advanced starts, it could lead to a crash when the game attempted to revive them, and queried the map, which didn't exist yet, for furniture at a point. --- src/game.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/game.cpp b/src/game.cpp index 9abc56945f598..6f7f853c8e19b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -5254,6 +5254,11 @@ bool game::revive_corpse( const tripoint &p, item &it ) debugmsg( "Tried to revive a non-corpse." ); return false; } + // If this is not here, the game may attempt to spawn a monster before the map exists, + // leading to it querying for furniture, and crashing. + if( g->new_game ) { + return false; + } shared_ptr_fast newmon_ptr = make_shared_fast ( it.get_mtype()->id ); if( it.has_var( "zombie_form" ) ) { // if the monster can reanimate has a zombie From 20c6554aa80e135bfea93f07cc38f93ba87cfa5b Mon Sep 17 00:00:00 2001 From: johnrdconnolly <59102789+johnrdconnolly@users.noreply.github.com> Date: Sat, 27 Jun 2020 23:03:06 -0700 Subject: [PATCH 08/41] add longest_side to entry_tools.json --- data/json/items/tool/entry_tools.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/data/json/items/tool/entry_tools.json b/data/json/items/tool/entry_tools.json index 4a2cf6dea0626..a07baa6ad5ae0 100644 --- a/data/json/items/tool/entry_tools.json +++ b/data/json/items/tool/entry_tools.json @@ -6,6 +6,7 @@ "description": "This is a hefty prying tool. Use it to open locked doors without destroying them or to lift manhole covers. You could also wield it to bash some heads in.", "weight": "500 g", "volume": "1 L", + "longest_side": "60 cm", "price": 1300, "price_postapoc": 500, "to_hit": -1, @@ -39,8 +40,9 @@ "type": "TOOL", "name": { "str": "ice axe" }, "description": "This is an ice axe with hammer on its head, a multi-purpose hiking and climbing tool used by mountaineers. It is sturdy enough to pry open closed doors or lift manhole covers.", - "weight": "500 g", + "weight": "239 g", "volume": "750 ml", + "longest_side": "45 cm", "price": 5000, "price_postapoc": 500, "to_hit": -2, @@ -59,8 +61,9 @@ "type": "TOOL", "name": { "str": "makeshift crowbar" }, "description": "This is a pipe whose ends have been bent and hammered flat to resemble a crowbar. Use it to open locked crates without destroying them, or to lift manhole covers. You could also wield it to fight with, in a pinch.", - "weight": "1250 g", + "weight": "1000 g", "volume": "1 L", + "longest_side": "60 cm", "price": 0, "price_postapoc": 10, "to_hit": -1, From f642c5b830b760cce3f1d83eed45b7486a0661a5 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sun, 28 Jun 2020 01:26:20 -0700 Subject: [PATCH 09/41] Prevent items from being the same volume as they can contain (#41647) * Warn on items having pockets exactly the same size No item should be able to perfectly contain a copy of itself. New volume values are 105% previous ones. * Fix containers with same volume as capacity Values used are 1.05x the previous volume --- data/json/items/armor/storage.json | 40 ++++++++++----------- data/json/items/containers.json | 22 ++++++------ data/json/items/generic/dining_kitchen.json | 36 ++++++++++--------- data/json/items/tool/container.json | 2 +- data/json/items/tool/cooking.json | 6 ++-- data/json/items/tool/med.json | 2 +- data/json/items/tool/misc.json | 2 +- data/mods/Aftershock/items/items.json | 2 +- data/mods/TEST_DATA/items.json | 6 ++-- src/item_contents.cpp | 2 +- 10 files changed, 61 insertions(+), 59 deletions(-) diff --git a/data/json/items/armor/storage.json b/data/json/items/armor/storage.json index 33ed9b9068752..9065d3482c926 100644 --- a/data/json/items/armor/storage.json +++ b/data/json/items/armor/storage.json @@ -35,7 +35,7 @@ "name": { "str": "hiking backpack" }, "description": "A large sized hiking backpack with plenty of storage space.", "weight": "2291 g", - "volume": "14 L", + "volume": "14700 ml", "price": 10000, "price_postapoc": 1000, "material": [ "leather" ], @@ -108,7 +108,7 @@ "name": { "str": "giant novelty backpack" }, "description": "A huge fabric backpack made mostly as a joke before the Cataclysm. Now, it's still rather silly, but it can store a lot of stuff.", "weight": "1200 g", - "volume": "8750 ml", + "volume": "9186 ml", "price": 4500, "price_postapoc": 750, "material": [ "cotton" ], @@ -224,7 +224,7 @@ "name": { "str": "laundry basket" }, "description": "A plastic basket meant for storing and hauling clothing.", "weight": "680 g", - "volume": "50 L", + "volume": "52500 ml", "price": 75, "price_postapoc": 10, "to_hit": -2, @@ -338,7 +338,7 @@ "symbol": "]", "looks_like": "jerrypack", "material": [ "wood", "cotton" ], - "volume": "15 L", + "volume": "15750 ml", "price_postapoc": 50, "pocket_data": [ { @@ -366,7 +366,7 @@ "name": { "str": "briefcase" }, "description": "Useful for carrying money, documents, or smuggled goods.", "weight": "1700 g", - "volume": "15 L", + "volume": "15750 ml", "price": 24000, "price_postapoc": 50, "to_hit": -2, @@ -398,7 +398,7 @@ "name": { "str": "violin case" }, "description": "Useful to carry your precious musical instrument around protected from any harm.", "weight": "2800 g", - "volume": "10 L", + "volume": "10500 ml", "price": 24000, "price_postapoc": 50, "to_hit": -4, @@ -433,7 +433,7 @@ "looks_like": "backpack", "color": "red", "weight": "411 g", - "volume": "2 L", + "volume": "2100 ml", "//": "REI Co-op 22-liter daypack costs $54.95, so ballpark to $55", "price": 5500, "price_postapoc": 500, @@ -523,7 +523,7 @@ "name": { "str": "tactical dump pouch", "str_pl": "tactical dump pouches" }, "description": "An expandable pouch secured with straps. Provides a bit of extra storage with minimal encumbrance.", "weight": "288 g", - "volume": "500 ml", + "volume": "525 ml", "price": 4500, "price_postapoc": 250, "to_hit": 2, @@ -556,7 +556,7 @@ "name": { "str": "fanny pack" }, "description": "Provides a bit of extra storage, with minimal encumbrance.", "weight": "272 g", - "volume": "1000 ml", + "volume": "1050 ml", "price": 3500, "to_hit": 2, "bashing": 1, @@ -708,7 +708,7 @@ "name": { "str": "jerrypack" }, "description": "A jerrycan modified to be worn in a similar manner to a backpack.", "weight": "1763 g", - "volume": "10 L", + "volume": "10500 ml", "price": 1450, "price_postapoc": 250, "to_hit": -1, @@ -769,7 +769,7 @@ "name": { "str": "pair of drop leg pouches", "str_pl": "pairs of drop leg pouches" }, "description": "A set of pouches that can be worn on the thighs using buckled straps. This variety is favored by the military.", "weight": "205 g", - "volume": "1 L", + "volume": "1050 ml", "price": 3000, "price_postapoc": 250, "material": [ "cotton" ], @@ -870,7 +870,7 @@ "//": "KA101's ran about $90 but is ballistic nylon. Bit tougher than the DDA model.", "description": "Light and easy to wear, but doesn't offer much storage.", "weight": "690 g", - "volume": "2500 ml", + "volume": "2625 ml", "price": 7900, "price_postapoc": 250, "to_hit": 1, @@ -958,7 +958,7 @@ "name": { "str": "petpack" }, "description": "Before the Cataclysm this would allow your four-legged friend to see the world, now it's used to shield them from the world.", "weight": "900 g", - "volume": "35 L", + "volume": "36750 ml", "price": 7900, "price_postapoc": 250, "material": [ "cotton", "plastic" ], @@ -1164,7 +1164,7 @@ "//": "Depends on if you're getting a cheap school version or something more like a range bag.", "description": "A simple single-sling backpack. Easier to access than a normal backpack, but can't comfortably hold as much.", "weight": "566 g", - "volume": "2 L", + "volume": "2100 ml", "price": 2900, "price_postapoc": 750, "bashing": 1, @@ -1196,7 +1196,7 @@ "name": { "str": "straw basket" }, "description": "Hand made straw basket. Carry it with you for extra storage.", "weight": "100 g", - "volume": "10 L", + "volume": "10500 ml", "price": 200, "price_postapoc": 50, "to_hit": -1, @@ -1228,7 +1228,7 @@ "//": "You drag it along with you, so it taking a hit is Rare.", "description": "A huge wheeled suitcase used mainly for transporting clothes and other possessions during trips, provides a decent amount of storage but hauling it around is neither fast nor comfortable.", "weight": "5000 g", - "volume": "110 L", + "volume": "115500 ml", "price": 21000, "price_postapoc": 500, "material": [ "plastic" ], @@ -1258,7 +1258,7 @@ "name": { "str": "suitcase" }, "description": "A mid-sized wheeled suitcase used mainly for transporting clothes and other possessions during trips, provides a decent amount of storage but hauling it around is not exactly comfortable.", "weight": "3000 g", - "volume": "45 L", + "volume": "47250 ml", "price": 21000, "price_postapoc": 250, "material": [ "cotton" ], @@ -1287,7 +1287,7 @@ "name": { "str": "survivor duffel bag" }, "description": "A custom-built heavy duffel bag. Durable and carefully crafted to hold as much stuff as possible.", "weight": "1000 g", - "volume": "7500 ml", + "volume": "7875 ml", "price": 24000, "price_postapoc": 3250, "material": [ "leather", "cotton" ], @@ -1317,7 +1317,7 @@ "name": { "str": "survivor backpack" }, "description": "A custom-built backpack. Durable and carefully crafted to hold as much stuff as possible.", "weight": "600 g", - "volume": "5000 ml", + "volume": "5250 ml", "price": 24000, "price_postapoc": 2250, "material": [ "leather", "cotton" ], @@ -1377,7 +1377,7 @@ "name": { "str": "survivor runner pack" }, "description": "A custom-built lightweight runner pack. Durable and carefully crafted to hold as much stuff as possible.", "weight": "440 g", - "volume": "4 L", + "volume": "4200 ml", "price": 24000, "price_postapoc": 2500, "material": [ "leather", "cotton" ], diff --git a/data/json/items/containers.json b/data/json/items/containers.json index 9046b973bad10..f088a75b17cfc 100644 --- a/data/json/items/containers.json +++ b/data/json/items/containers.json @@ -6,7 +6,7 @@ "name": { "str": "2.5L canteen" }, "description": "A large plastic water canteen, with a 2.5 liter capacity and carrying strap.", "weight": "155 g", - "volume": "2500 ml", + "volume": "2625 ml", "price": 1000, "price_postapoc": 50, "to_hit": -1, @@ -34,7 +34,7 @@ "name": { "str": "30 gallon barrel" }, "description": "A huge plastic barrel with a resealable lid.", "weight": "6800 g", - "volume": "112500 ml", + "volume": "118125 ml", "price": 5000, "price_postapoc": 250, "to_hit": -5, @@ -60,7 +60,7 @@ "name": { "str": "steel drum (100L)", "str_pl": "steel drums (100L)" }, "description": "A huge steel barrel with a resealable lid.", "weight": "12000 g", - "volume": "100 L", + "volume": "105 L", "price": 8000, "price_postapoc": 250, "to_hit": -5, @@ -86,7 +86,7 @@ "name": { "str": "steel drum (200L)", "str_pl": "steel drums (200L)" }, "description": "A massive steel barrel with a resealable lid.", "weight": "20000 g", - "volume": "200 L", + "volume": "210 L", "price": 10000, "price_postapoc": 250, "to_hit": -5, @@ -246,7 +246,7 @@ "name": { "str": "glass bottle" }, "description": "A resealable glass bottle, holds 750 ml of liquid.", "weight": "200 g", - "volume": "750 ml", + "volume": "787 ml", "price": 0, "price_postapoc": 10, "to_hit": 1, @@ -302,7 +302,7 @@ "name": { "str": "condiment bottle" }, "description": "An inverted plastic bottle for condiments. Still sealed from factory, preserves content from rot until opened.", "weight": "19 g", - "volume": "500 ml", + "volume": "525 ml", "pocket_data": [ { "pocket_type": "CONTAINER", @@ -330,7 +330,7 @@ "name": { "str": "condiment bottle" }, "description": "An inverted plastic bottle for condiments.", "weight": "19 g", - "volume": "500 ml", + "volume": "525 ml", "pocket_data": [ { "pocket_type": "CONTAINER", @@ -463,7 +463,7 @@ "name": { "str": "cardboard box", "str_pl": "cardboard boxes" }, "description": "A sturdy cardboard box, about the size of a banana box. Great for packing.", "weight": "850 g", - "volume": "2 L", + "volume": "2100 ml", "//": "Volume is much lower than the actual volume of a box this size because presumably if it's in your pack, it isn't empty and full of air; and if it's in your hands, it's irrelevant what the volume is.", "price": 0, "price_postapoc": 0, @@ -487,7 +487,7 @@ "name": { "str": "large cardboard box", "str_pl": "large cardboard boxes" }, "description": "A very large cardboard box, the sort children would have loved to hide in, when there were still children.", "weight": "1250 g", - "volume": "3 L", + "volume": "3150 ml", "//": "Volume is much lower than the actual volume of a box this size because presumably if it's in your pack, it isn't empty and full of air; and if it's in your hands, it's irrelevant what the volume is.", "price": 0, "price_postapoc": 10, @@ -816,7 +816,7 @@ "name": { "str": "plastic cup" }, "description": "A small, vacuum formed cup.", "weight": "6 g", - "volume": "250 ml", + "volume": "262 ml", "price": 0, "price_postapoc": 0, "to_hit": 1, @@ -1620,7 +1620,7 @@ "name": { "str": "small cardboard box of tea bags", "str_pl": "small cardboard boxes of tea bags" }, "description": "A very small cardboard box with tea brand written on it.", "weight": "10 g", - "volume": "100 ml", + "volume": "105 ml", "price": 0, "price_postapoc": 0, "material": [ "cardboard" ], diff --git a/data/json/items/generic/dining_kitchen.json b/data/json/items/generic/dining_kitchen.json index d8e161dce906b..2b542c6a0738d 100644 --- a/data/json/items/generic/dining_kitchen.json +++ b/data/json/items/generic/dining_kitchen.json @@ -58,7 +58,7 @@ "price_postapoc": 0, "material": [ "ceramic" ], "weight": "322 g", - "volume": "250 ml", + "volume": "262 ml", "bashing": 3, "to_hit": -1 }, @@ -73,7 +73,7 @@ "price_postapoc": 0, "material": [ "glass" ], "weight": "322 g", - "volume": "250 ml", + "volume": "262 ml", "bashing": 3, "to_hit": -1 }, @@ -88,7 +88,7 @@ "price_postapoc": 0, "material": [ "tin" ], "weight": "262 g", - "volume": "250 ml", + "volume": "262 ml", "bashing": 2, "to_hit": -1 }, @@ -103,7 +103,7 @@ "price_postapoc": 0, "material": [ "plastic" ], "weight": "130 g", - "volume": "250 ml", + "volume": "262 ml", "bashing": 1, "to_hit": -1 }, @@ -138,7 +138,7 @@ "symbol": ")", "description": "A perfectly ordinary ceramic soup bowl.", "copy-from": "base_ceramic_dish", - "volume": "500 ml", + "volume": "525 ml", "pocket_data": [ { "max_contains_volume": "500 ml", @@ -154,6 +154,7 @@ "type": "GENERIC", "category": "other", "id": "ceramic_cup", + "volume": "262 ml", "name": { "str": "ceramic cup" }, "symbol": "u", "description": "A light ceramic teacup. Quite classy.", @@ -300,6 +301,7 @@ "type": "GENERIC", "category": "other", "id": "wine_glass", + "volume": "262 ml", "name": { "str": "wine glass", "str_pl": "wine glasses" }, "proportional": { "weight": 0.5 }, "symbol": "Y", @@ -324,7 +326,7 @@ "symbol": "u", "description": "A glass bowl for soup or dessert.", "copy-from": "base_glass_dish", - "volume": "500 ml", + "volume": "525 ml", "pocket_data": [ { "max_contains_volume": "500 ml", @@ -373,7 +375,7 @@ "symbol": "u", "description": "A plastic bowl with a convenient sealing lid. Holds 750 ml of liquid.", "copy-from": "base_plastic_dish", - "volume": "750 ml", + "volume": "787 ml", "pocket_data": [ { "pocket_type": "CONTAINER", @@ -703,7 +705,7 @@ "material": [ "steel" ], "color": "light_gray", "weight": "550 g", - "volume": "2 L", + "volume": "2100 ml", "bashing": 6, "pocket_data": [ { @@ -725,7 +727,7 @@ "material": [ "iron" ], "color": "dark_gray", "weight": "3000 g", - "volume": "2 L", + "volume": "2100 ml", "bashing": 10, "pocket_data": [ { @@ -747,7 +749,7 @@ "material": [ "copper" ], "color": "light_red", "weight": "750 g", - "volume": "2 L", + "volume": "2100 ml", "bashing": 6, "to_hit": -2, "pocket_data": [ @@ -770,7 +772,7 @@ "material": [ "ceramic" ], "color": "white", "weight": "650 g", - "volume": "2 L", + "volume": "2100 ml", "bashing": 4, "pocket_data": [ { @@ -811,7 +813,7 @@ "name": { "str": "canning pot" }, "description": "A very large 25 liter pot, primarily meant for canning food in glass jars via the water bath method, though it can cook normal foods just as well. Canning foods with it will require a lot of water. If you're only canning a couple of jars at a time, you'd fill it up with rocks or something to displace the water above the lids.", "weight": "5625 g", - "volume": "25 L", + "volume": "26250 ml", "price": 20000, "to_hit": -2, "bashing": 10, @@ -841,7 +843,7 @@ "material": [ "iron" ], "color": "dark_gray", "weight": "2628 g", - "volume": "1 L", + "volume": "1050 ml", "bashing": 12, "to_hit": -3, "pocket_data": [ @@ -893,7 +895,7 @@ "color": "light_red", "looks_like": "pan", "weight": "628 g", - "volume": "1 L", + "volume": "1050 ml", "bashing": 7, "to_hit": -2, "pocket_data": [ @@ -915,7 +917,7 @@ "name": { "str": "makeshift pot" }, "description": "A sheet of metal crudely hammered into a cooking pot. Good enough to cook food and boil water, but not as useful as proper cookware.", "weight": "6000 g", - "volume": "1 L", + "volume": "1050 ml", "price": 200, "price_postapoc": 5, "to_hit": 1, @@ -942,7 +944,7 @@ "name": { "str": "makeshift copper pot" }, "description": "A cooking pot crudely hammered out of copper. Good enough to cook food and boil water, but not as useful as proper cookware.", "weight": "884 g", - "volume": "1 L", + "volume": "1050 ml", "price": 200, "price_postapoc": 5, "to_hit": 1, @@ -972,7 +974,7 @@ "material": [ "steel" ], "color": "light_gray", "weight": "728 g", - "volume": "1500 ml", + "volume": "1575 ml", "bashing": 5, "pocket_data": [ { "max_contains_volume": "1500 ml", "max_contains_weight": "2 kg", "watertight": true, "rigid": true } ], "delete": { "qualities": [ [ "COOK", 3 ] ] } diff --git a/data/json/items/tool/container.json b/data/json/items/tool/container.json index 0daed8a9d5915..e643ff47cf46d 100644 --- a/data/json/items/tool/container.json +++ b/data/json/items/tool/container.json @@ -6,7 +6,7 @@ "name": { "str": "steel bottle" }, "description": "A stainless steel water bottle, holds 750ml of liquid.", "weight": "200 g", - "volume": "750 ml", + "volume": "787 ml", "price": 0, "price_postapoc": 10, "to_hit": 1, diff --git a/data/json/items/tool/cooking.json b/data/json/items/tool/cooking.json index f0a9298c97859..8e627371380a3 100644 --- a/data/json/items/tool/cooking.json +++ b/data/json/items/tool/cooking.json @@ -177,7 +177,7 @@ "name": { "str": "clay pot" }, "description": "A crude clay pot with lid used for cooking.", "weight": "480 g", - "volume": "2 L", + "volume": "2100 ml", "price": 2500, "price_postapoc": 10, "bashing": 1, @@ -210,7 +210,7 @@ "name": { "str": "clay teapot" }, "description": "A clay teapot. Now all you need is tea and water.", "weight": "429 g", - "volume": "750 ml", + "volume": "787 ml", "price": 2000, "price_postapoc": 10, "to_hit": 1, @@ -958,7 +958,7 @@ "name": { "str": "teapot" }, "description": "A small metal teapot. Teatime wouldn't be complete without one.", "weight": "229 g", - "volume": "500 ml", + "volume": "525 ml", "price": 1000, "price_postapoc": 10, "to_hit": 2, diff --git a/data/json/items/tool/med.json b/data/json/items/tool/med.json index c0db5ebb543c8..2c846b64cfe19 100644 --- a/data/json/items/tool/med.json +++ b/data/json/items/tool/med.json @@ -187,7 +187,7 @@ "name": { "str": "blood draw kit" }, "description": "This is a kit for drawing blood, including a test tube for holding the sample. Use this tool to draw blood, either from yourself or from a corpse you are standing on.", "weight": "13 g", - "volume": "250 ml", + "volume": "262 ml", "price": 3000, "price_postapoc": 100, "to_hit": -3, diff --git a/data/json/items/tool/misc.json b/data/json/items/tool/misc.json index 2d1a06abe02ba..6a6e614a7bdbe 100644 --- a/data/json/items/tool/misc.json +++ b/data/json/items/tool/misc.json @@ -833,7 +833,7 @@ "name": { "str": "sandbox kit" }, "description": "A plastic bucket holding a small spade and rake, perfect to build sand castles!", "weight": "250 g", - "volume": "1 L", + "volume": "1050 ml", "price": 300, "price_postapoc": 3, "material": [ "plastic" ], diff --git a/data/mods/Aftershock/items/items.json b/data/mods/Aftershock/items/items.json index 9673c7f78054e..7251757f304da 100644 --- a/data/mods/Aftershock/items/items.json +++ b/data/mods/Aftershock/items/items.json @@ -20,7 +20,7 @@ "description": "A wide, shallow basin used to hold liquid, hammered from a piece of sheet metal. Ideal for collecting water.", "weight": "5 kg", "looks_like": "ceramic_bowl", - "volume": "2500 ml", + "volume": "2625 ml", "price": 1000, "to_hit": -1, "bashing": 1, diff --git a/data/mods/TEST_DATA/items.json b/data/mods/TEST_DATA/items.json index ee58dd44714f8..0da4fd0a1ea26 100644 --- a/data/mods/TEST_DATA/items.json +++ b/data/mods/TEST_DATA/items.json @@ -559,7 +559,7 @@ "name": "TEST gallon jug", "description": "A standard plastic jug used for milk and household cleaning chemicals.", "weight": "190 g", - "volume": "3750 ml", + "volume": "3938 ml", "price": 0, "to_hit": 1, "material": [ "plastic" ], @@ -662,7 +662,7 @@ "name": "TEST briefcase", "description": "Useful for carrying money, documents, or smuggled goods.", "weight": "1700 g", - "volume": "15 L", + "volume": "15750 ml", "price": 24000, "to_hit": -2, "bashing": 5, @@ -919,7 +919,7 @@ "name": { "str": "test box" }, "description": "A simple 1-liter cardboard box of deliberately undefined proportions.", "weight": "100 g", - "volume": "1 L", + "volume": "1050 ml", "price": 0, "price_postapoc": 25, "material": [ "cardboard" ], diff --git a/src/item_contents.cpp b/src/item_contents.cpp index 04165d4e253bc..cea650f10942b 100644 --- a/src/item_contents.cpp +++ b/src/item_contents.cpp @@ -251,7 +251,7 @@ bool item_contents::bigger_on_the_inside( const units::volume &container_volume } } } - return container_volume < min_logical_volume; + return container_volume <= min_logical_volume; } size_t item_contents::size() const From 3e75c4be4d6a83fecd5f8ad0a168602cc3beaf58 Mon Sep 17 00:00:00 2001 From: Fris0uman <41293484+Fris0uman@users.noreply.github.com> Date: Sun, 28 Jun 2020 11:40:26 +0200 Subject: [PATCH 10/41] Fix connector drawing in bionic menu (#41625) --- src/bionics_ui.cpp | 13 +++++++++---- src/creature.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/bionics_ui.cpp b/src/bionics_ui.cpp index db94ec0b93062..25f2f09cb55ec 100644 --- a/src/bionics_ui.cpp +++ b/src/bionics_ui.cpp @@ -267,13 +267,16 @@ static void draw_description( const catacurses::window &win, const bionic &bio ) } static void draw_connectors( const catacurses::window &win, const point &start, - int last_x, const bionic_id &bio_id ) + int last_x, const bionic_id &bio_id, const std::map &bp_to_pos ) { const int LIST_START_Y = 7; // first: pos_y, second: occupied slots std::vector> pos_and_num; for( const std::pair, size_t> &elem : bio_id->occupied_bodyparts ) { - pos_and_num.emplace_back( static_cast( elem.first->token ) + LIST_START_Y, elem.second ); + auto pos = bp_to_pos.find( elem.first ); + if( pos != bp_to_pos.end() ) { + pos_and_num.emplace_back( pos->second + LIST_START_Y, elem.second ); + } } if( pos_and_num.empty() || !get_option < bool >( "CBM_SLOTS_ENABLED" ) ) { return; @@ -525,12 +528,14 @@ void player::power_bionics() int max_width = 0; std::vector bps; + std::map bp_to_pos; for( const bodypart_id &bp : get_all_body_parts() ) { const int total = get_total_bionics_slots( bp ); const std::string s = string_format( "%s: %d/%d", body_part_name_as_heading( bp, 1 ), total - get_free_bionics_slots( bp ), total ); bps.push_back( s ); + bp_to_pos.emplace( bp.id(), bps.size() - 1 ); max_width = std::max( max_width, utf8_width( s ) ); } const int pos_x = WIDTH - 2 - max_width; @@ -567,11 +572,11 @@ void player::power_bionics() if( is_highlighted && menu_mode != EXAMINING && get_option < bool >( "CBM_SLOTS_ENABLED" ) ) { const bionic_id bio_id = ( *current_bionic_list )[i]->id; draw_connectors( wBio, point( utf8_width( desc ) + 3, list_start_y + i - scroll_position ), - pos_x - 2, bio_id ); + pos_x - 2, bio_id, bp_to_pos ); // redraw highlighted (occupied) body parts for( const std::pair, size_t> &elem : bio_id->occupied_bodyparts ) { - const int i = static_cast( elem.first->token ); + const int i = bp_to_pos[elem.first]; mvwprintz( wBio, point( pos_x, i + list_start_y ), c_yellow, bps[i] ); } } diff --git a/src/creature.h b/src/creature.h index be16c662cfc7a..f17b3a727eafd 100644 --- a/src/creature.h +++ b/src/creature.h @@ -600,7 +600,7 @@ class Creature bodypart_id get_random_body_part( bool main = false ) const; /** - * Returns body parts in order in which they should be displayed. + * Returns body parts this creature have. * @param only_main If true, only displays parts that can have hit points */ std::vector get_all_body_parts( bool only_main = false ) const; From 5e97a26c628eeefaf88a7f0727cb79128e1d3395 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Sun, 28 Jun 2020 15:38:47 +0300 Subject: [PATCH 11/41] Wrap all lone top level json objects in arrays Convert ``` { "type": "foo", ... } ``` into ``` [ { "type": "foo", ... } ] ``` More uniform json structure makes using jq and writing tooling easier. --- data/mods/DinoMod/hints.json | 30 +- data/mods/DinoMod/lab_notes.json | 24 +- data/mods/DinoMod/mapgen/DinoLabFinale.json | 170 +- .../gunmods/gg_gunmods_blacklist.json | 48 +- .../magazines/gg_magazines_blacklist.json | 14 +- .../My_Sweet_Cataclysm/sweet_snippets.json | 22 +- data/mods/default.json | 19 +- .../Examples/office_template.json | 147 +- .../Examples/office_terrain_template.json | 32 +- .../Examples/output_office_template.json | 2980 ++++++++--------- .../output_office_terrain_template.json | 322 +- 11 files changed, 1900 insertions(+), 1908 deletions(-) diff --git a/data/mods/DinoMod/hints.json b/data/mods/DinoMod/hints.json index aa9a0929281f8..ba04cc89fbe86 100644 --- a/data/mods/DinoMod/hints.json +++ b/data/mods/DinoMod/hints.json @@ -1,14 +1,16 @@ -{ - "type": "snippet", - "category": "hint", - "text": [ - "I've seen some big dinosaurs out there. I know that should be scary, but all I felt was hungry.", - "I think those little dinosaurs are kind of cute, like a cat kind of. Do you think they eat cat food?", - "Dinosaurs are a bow hunter's best friend. Feathers forever!", - "A buddy of mine wandered close to the swamps and was eaten by a T-Rex, a big lizard. I'd be careful unless you have a gun and plenty of ammo.", - "I hear the zombies have been in the swamps. Bad news if they bite a dinosaur before it bites them.", - "I know there aren't alligators in the sewer, but I heard there was some kind of big lizard down there. Probably not a good idea to check.", - "Some of those big dinosaurs seem halfway all right. I bet if you fed them something nice and gave them a pet you could ride them like a pony. Or maybe they'd eat you instead.", - "One time I found a strange egg out in the woods. It was probably a dinosaur, but I cooked it and it was pretty good!" - ] -} +[ + { + "type": "snippet", + "category": "hint", + "text": [ + "I've seen some big dinosaurs out there. I know that should be scary, but all I felt was hungry.", + "I think those little dinosaurs are kind of cute, like a cat kind of. Do you think they eat cat food?", + "Dinosaurs are a bow hunter's best friend. Feathers forever!", + "A buddy of mine wandered close to the swamps and was eaten by a T-Rex, a big lizard. I'd be careful unless you have a gun and plenty of ammo.", + "I hear the zombies have been in the swamps. Bad news if they bite a dinosaur before it bites them.", + "I know there aren't alligators in the sewer, but I heard there was some kind of big lizard down there. Probably not a good idea to check.", + "Some of those big dinosaurs seem halfway all right. I bet if you fed them something nice and gave them a pet you could ride them like a pony. Or maybe they'd eat you instead.", + "One time I found a strange egg out in the woods. It was probably a dinosaur, but I cooked it and it was pretty good!" + ] + } +] diff --git a/data/mods/DinoMod/lab_notes.json b/data/mods/DinoMod/lab_notes.json index b1a4ed17a7c93..1c510ded13218 100644 --- a/data/mods/DinoMod/lab_notes.json +++ b/data/mods/DinoMod/lab_notes.json @@ -1,11 +1,13 @@ -{ - "type": "snippet", - "category": "lab_notes", - "text": [ - "Research on our visitors is proceeding nicely. The raptor DNA is of special interest, with some novel protein chains that may lead to medical breakthroughs.", - "Research proceeds apace on our visitors. While Operation Major Laser did not receive enough funding as hoped, our more humble bio-operator protocols were already prepared and are proceeding ahead of schedule. The hosts are most receptive to improvement.", - "Dr. Yoshimi has been reprimanded for unauthorized contact with the procompsignathids. Disgusting behavior, and a terrible example to the junior researchers.", - "Dr. Yoshimi has escaped, along with an unknown number of dinosaurs. Unfortunately, we have bigger problems with XE037.", - "Strange sounds have been reported from the swamp nearby. An enhanced security team was dispatched, but has not returned in 48 hours. The facility is on lockdown. We can’t let them get back in." - ] -} +[ + { + "type": "snippet", + "category": "lab_notes", + "text": [ + "Research on our visitors is proceeding nicely. The raptor DNA is of special interest, with some novel protein chains that may lead to medical breakthroughs.", + "Research proceeds apace on our visitors. While Operation Major Laser did not receive enough funding as hoped, our more humble bio-operator protocols were already prepared and are proceeding ahead of schedule. The hosts are most receptive to improvement.", + "Dr. Yoshimi has been reprimanded for unauthorized contact with the procompsignathids. Disgusting behavior, and a terrible example to the junior researchers.", + "Dr. Yoshimi has escaped, along with an unknown number of dinosaurs. Unfortunately, we have bigger problems with XE037.", + "Strange sounds have been reported from the swamp nearby. An enhanced security team was dispatched, but has not returned in 48 hours. The facility is on lockdown. We can’t let them get back in." + ] + } +] diff --git a/data/mods/DinoMod/mapgen/DinoLabFinale.json b/data/mods/DinoMod/mapgen/DinoLabFinale.json index 79b63086be8de..5a49179a2fd33 100644 --- a/data/mods/DinoMod/mapgen/DinoLabFinale.json +++ b/data/mods/DinoMod/mapgen/DinoLabFinale.json @@ -1,87 +1,87 @@ -{ - "//": "dino operating theater", - "type": "mapgen", - "method": "json", - "om_terrain": [ - "lab_finale_1level" - ], - "weight": 75, - "object": { - "rotation": [ 0, 3 ], - "fill_ter": "t_thconc_floor", - "rows": [ - "..cccccc.|...|,,,|..|,,,", - "c........|...|,,,|.6|,,,", - "c..Ccxc..|...|,,,g..g,,,", - "c........g...|,,,g..g,,,", - "c........g...|,,,L..L,,,", - "......llS|...|---|..|---", - "--gg-G---|...|,,,|..|,,,", - ".............|,,,g..g,,,", - ".............|,,,g..g,,,", - ".............|,,,L..L,,,", - "........|-ggg----|..|---", - "........|r,,,r|t--G-|...", - "........g,,/,,L.....G...", - "........g,,?,,|-ggg-|...", - "........|r,,,r|.........", - "........|-ggg-|.........", - "........................", - "........................", - "..........dd7dd.........", - "..........d.h.d.........", - "...ddxdd.........ddxdd..", - "...d.h.d.........d.h.d..", - "........................", - "........................" - ], - "palettes": [ "lab_palette", "lab_loot_research" ], - "furniture": { "?": "f_autodoc", "/": "f_autodoc_couch" }, - "terrain": { - ",": "t_floor_blue", - "C": "t_centrifuge", - "?": "t_floor_blue", - "/": "t_floor_blue", - "7": "t_console", - "r": "t_floor_blue" - }, - "place_loot": [ - { "item": "anesthetic_kit", "x": 15, "y": 11, "repeat": [ 4, 9 ], "ammo": 100 }, - { "item": "id_science", "x": 7, "y": 11, "chance": 100 }, - { "item": "cattlefodder", "x": 7, "y": 11, "chance": 100 } - ], - "mapping": { - "r": { - "items": [ - { "item": "bionics_common", "chance": 40 }, - { "item": "bionics", "chance": 20 }, - { "item": "hospital_medical_items", "chance": 80 }, - { "item": "dissection", "chance": 60 } - ] - } - }, - "computers": { - "6": { - "name": "DinoLab Operating Theater Controls", - "security": 0, - "options": [ { "name": "EMERGENCY EVAC - OPEN ALL DOORS", "action": "open", "security": 0 } ], - "failures": [ { "action": "damage" }, { "action": "shutdown" } ] +[ + { + "//": "dino operating theater", + "type": "mapgen", + "method": "json", + "om_terrain": [ "lab_finale_1level" ], + "weight": 75, + "object": { + "rotation": [ 0, 3 ], + "fill_ter": "t_thconc_floor", + "rows": [ + "..cccccc.|...|,,,|..|,,,", + "c........|...|,,,|.6|,,,", + "c..Ccxc..|...|,,,g..g,,,", + "c........g...|,,,g..g,,,", + "c........g...|,,,L..L,,,", + "......llS|...|---|..|---", + "--gg-G---|...|,,,|..|,,,", + ".............|,,,g..g,,,", + ".............|,,,g..g,,,", + ".............|,,,L..L,,,", + "........|-ggg----|..|---", + "........|r,,,r|t--G-|...", + "........g,,/,,L.....G...", + "........g,,?,,|-ggg-|...", + "........|r,,,r|.........", + "........|-ggg-|.........", + "........................", + "........................", + "..........dd7dd.........", + "..........d.h.d.........", + "...ddxdd.........ddxdd..", + "...d.h.d.........d.h.d..", + "........................", + "........................" + ], + "palettes": [ "lab_palette", "lab_loot_research" ], + "furniture": { "?": "f_autodoc", "/": "f_autodoc_couch" }, + "terrain": { + ",": "t_floor_blue", + "C": "t_centrifuge", + "?": "t_floor_blue", + "/": "t_floor_blue", + "7": "t_console", + "r": "t_floor_blue" }, - "7": { - "name": "DinoLab Operating Theater Controls", - "security": 2, - "options": [ { "name": "UNLOCK AUTODOC DOOR", "action": "unlock", "security": 6 } ], - "failures": [ { "action": "damage" }, { "action": "shutdown" } ] - } - }, - "place_monster": [ - { "monster": [ "mon_deino_bio_op" ], "x": [ 14, 16 ], "y": [ 1, 4 ], "chance": 90 }, - { "monster": [ "mon_deino_bio_op" ], "x": [ 14, 16 ], "y": [ 6, 9 ], "chance": 90 }, - { "monster": [ "mon_deino_bio_op" ], "x": [ 21, 22 ], "y": [ 1, 4 ], "chance": 90 }, - { "monster": [ "mon_deino_bio_op" ], "x": [ 21, 22 ], "y": [ 6, 9 ], "chance": 90 }, - { "monster": [ "mon_trice_bio_op" ], "x": [ 11, 13 ], "y": [ 13, 14 ], "chance": 100 }, - { "monster": "mon_zeinonychus", "x": [ 15, 19 ], "y": 12, "chance": 90, "repeat": [ 1, 2 ] }, - { "monster": "mon_zeinonychus", "x": [ 9, 10 ], "y": [ 12, 13 ] } - ] + "place_loot": [ + { "item": "anesthetic_kit", "x": 15, "y": 11, "repeat": [ 4, 9 ], "ammo": 100 }, + { "item": "id_science", "x": 7, "y": 11, "chance": 100 }, + { "item": "cattlefodder", "x": 7, "y": 11, "chance": 100 } + ], + "mapping": { + "r": { + "items": [ + { "item": "bionics_common", "chance": 40 }, + { "item": "bionics", "chance": 20 }, + { "item": "hospital_medical_items", "chance": 80 }, + { "item": "dissection", "chance": 60 } + ] + } + }, + "computers": { + "6": { + "name": "DinoLab Operating Theater Controls", + "security": 0, + "options": [ { "name": "EMERGENCY EVAC - OPEN ALL DOORS", "action": "open", "security": 0 } ], + "failures": [ { "action": "damage" }, { "action": "shutdown" } ] + }, + "7": { + "name": "DinoLab Operating Theater Controls", + "security": 2, + "options": [ { "name": "UNLOCK AUTODOC DOOR", "action": "unlock", "security": 6 } ], + "failures": [ { "action": "damage" }, { "action": "shutdown" } ] + } + }, + "place_monster": [ + { "monster": [ "mon_deino_bio_op" ], "x": [ 14, 16 ], "y": [ 1, 4 ], "chance": 90 }, + { "monster": [ "mon_deino_bio_op" ], "x": [ 14, 16 ], "y": [ 6, 9 ], "chance": 90 }, + { "monster": [ "mon_deino_bio_op" ], "x": [ 21, 22 ], "y": [ 1, 4 ], "chance": 90 }, + { "monster": [ "mon_deino_bio_op" ], "x": [ 21, 22 ], "y": [ 6, 9 ], "chance": 90 }, + { "monster": [ "mon_trice_bio_op" ], "x": [ 11, 13 ], "y": [ 13, 14 ], "chance": 100 }, + { "monster": "mon_zeinonychus", "x": [ 15, 19 ], "y": 12, "chance": 90, "repeat": [ 1, 2 ] }, + { "monster": "mon_zeinonychus", "x": [ 9, 10 ], "y": [ 12, 13 ] } + ] + } } -} +] diff --git a/data/mods/Generic_Guns/gunmods/gg_gunmods_blacklist.json b/data/mods/Generic_Guns/gunmods/gg_gunmods_blacklist.json index 338c6338da274..dcdc92531250c 100644 --- a/data/mods/Generic_Guns/gunmods/gg_gunmods_blacklist.json +++ b/data/mods/Generic_Guns/gunmods/gg_gunmods_blacklist.json @@ -1,23 +1,25 @@ -{ - "type": "ITEM_BLACKLIST", - "whitelist": false, - "items": [ - "lemat_revolver_shotgun", - "llink", - "dias", - "M6_shotgun", - "ksg_aux_shotgun", - "ksg25_aux_shotgun", - "combination_gun_shotgun", - "combination_gun_shotgun_pipe", - "belt_clip", - "retool_ar15_300blk", - "ts12_aux_shotgun", - "ts12_aux_shotgun2", - "lwfeed", - "lead_barrel_big", - "lead_barrel_heavy_duty", - "inter_bayonet", - "factory_handguard" - ] -} +[ + { + "type": "ITEM_BLACKLIST", + "whitelist": false, + "items": [ + "lemat_revolver_shotgun", + "llink", + "dias", + "M6_shotgun", + "ksg_aux_shotgun", + "ksg25_aux_shotgun", + "combination_gun_shotgun", + "combination_gun_shotgun_pipe", + "belt_clip", + "retool_ar15_300blk", + "ts12_aux_shotgun", + "ts12_aux_shotgun2", + "lwfeed", + "lead_barrel_big", + "lead_barrel_heavy_duty", + "inter_bayonet", + "factory_handguard" + ] + } +] diff --git a/data/mods/Generic_Guns/magazines/gg_magazines_blacklist.json b/data/mods/Generic_Guns/magazines/gg_magazines_blacklist.json index 5c231166b1920..3283ee853d85c 100644 --- a/data/mods/Generic_Guns/magazines/gg_magazines_blacklist.json +++ b/data/mods/Generic_Guns/magazines/gg_magazines_blacklist.json @@ -1,7 +1,7 @@ -{ - "type": "ITEM_BLACKLIST", - "whitelist": false, - "items": [ - "m74_clip" - ] -} +[ + { + "type": "ITEM_BLACKLIST", + "whitelist": false, + "items": [ "m74_clip" ] + } +] diff --git a/data/mods/My_Sweet_Cataclysm/sweet_snippets.json b/data/mods/My_Sweet_Cataclysm/sweet_snippets.json index 4a0690dd0d4f3..01424e780f204 100644 --- a/data/mods/My_Sweet_Cataclysm/sweet_snippets.json +++ b/data/mods/My_Sweet_Cataclysm/sweet_snippets.json @@ -1,10 +1,12 @@ -{ - "type": "snippet", - "category": "flier", - "text": [ - { - "id": "flier_my_sweet_cataclysm_1", - "text": "A flyer for some kind of candy. It shows a picture of a gleaming human made of smooth candy looking at you in terror. \"SugarKin the first life-size human candy! Are you a real monster? Will you be able to devour it all?\"" - } - ] -} +[ + { + "type": "snippet", + "category": "flier", + "text": [ + { + "id": "flier_my_sweet_cataclysm_1", + "text": "A flyer for some kind of candy. It shows a picture of a gleaming human made of smooth candy looking at you in terror. \"SugarKin the first life-size human candy! Are you a real monster? Will you be able to devour it all?\"" + } + ] + } +] diff --git a/data/mods/default.json b/data/mods/default.json index 0b73848d036ac..75f02b0fd2ec8 100644 --- a/data/mods/default.json +++ b/data/mods/default.json @@ -1,10 +1,9 @@ -{ - "type": "MOD_INFO", - "ident": "dev:default", - "name": "default", - "description": "contains all the mods recommended by the developers", - "dependencies": [ - "dda", - "no_npc_food" - ] -} +[ + { + "type": "MOD_INFO", + "ident": "dev:default", + "name": "default", + "description": "contains all the mods recommended by the developers", + "dependencies": [ "dda", "no_npc_food" ] + } +] diff --git a/utilities/building-utility/Examples/office_template.json b/utilities/building-utility/Examples/office_template.json index e51049741c8bf..3a43af797385c 100644 --- a/utilities/building-utility/Examples/office_template.json +++ b/utilities/building-utility/Examples/office_template.json @@ -1,84 +1,75 @@ -{ - "type" : "mapgen", - "om_terrain" : ["office_tower_"], +[ + { + "type": "mapgen", + "om_terrain": [ "office_tower_" ], "method": "json", "weight": 250, "_Building_Utility": { - "cell_map": { - "object_replace": [ - "object", - "rows" - ] - }, - "cell_num": { - "string_format": { - "office_tower_%s": [ - "om_terrain" - ] - } - } + "cell_map": { "object_replace": [ "object", "rows" ] }, + "cell_num": { "string_format": { "office_tower_%s": [ "om_terrain" ] } } }, "object": { - "fill_ter": "t_floor", - "rows": [], - "terrain": { - "/": "t_sky", - "~": "t_rock", - ">": "t_stairs_down", - "<": "t_stairs_up", - ".": "t_floor", - " ": "t_dirt", - "x": "t_console_broken", - ",": "t_pavement_y", - "_": "t_pavement", - "%": "t_shrub", - "+": "t_door_c", - "{": "t_rubble", - ")": "t_wreckage", - "}": "t_manhole_cover", - "@": "t_floor", - "2": "t_utility_light", - "b": "t_dirt", - "c": "t_floor", - "D": "t_door_metal_c", - "d": "t_floor", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "h": "t_floor", - "I": "t_column", - "k": "t_floor", - "L": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "^": "t_floor", - "p": "t_floor", - "R": "t_railing_v", - "r": "t_floor", - "S": "t_floor", - "s": "t_sidewalk", - "T": "t_floor", - "u": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "z": "t_floor" - }, - "furniture": { - "@": "f_bed", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "^": "f_indoor_plant", - "r": "f_rack", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "z": "f_crate_c" - } + "fill_ter": "t_floor", + "rows": [ ], + "terrain": { + "/": "t_sky", + "~": "t_rock", + ">": "t_stairs_down", + "<": "t_stairs_up", + ".": "t_floor", + " ": "t_dirt", + "x": "t_console_broken", + ",": "t_pavement_y", + "_": "t_pavement", + "%": "t_shrub", + "+": "t_door_c", + "{": "t_rubble", + ")": "t_wreckage", + "}": "t_manhole_cover", + "@": "t_floor", + "2": "t_utility_light", + "b": "t_dirt", + "c": "t_floor", + "D": "t_door_metal_c", + "d": "t_floor", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "h": "t_floor", + "I": "t_column", + "k": "t_floor", + "L": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "^": "t_floor", + "p": "t_floor", + "R": "t_railing_v", + "r": "t_floor", + "S": "t_floor", + "s": "t_sidewalk", + "T": "t_floor", + "u": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "z": "t_floor" + }, + "furniture": { + "@": "f_bed", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "^": "f_indoor_plant", + "r": "f_rack", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "z": "f_crate_c" + } } -} + } +] diff --git a/utilities/building-utility/Examples/office_terrain_template.json b/utilities/building-utility/Examples/office_terrain_template.json index 42a483c55d15b..19c342d1488fc 100644 --- a/utilities/building-utility/Examples/office_terrain_template.json +++ b/utilities/building-utility/Examples/office_terrain_template.json @@ -1,19 +1,13 @@ -{ - "type" : "overmap_terrain", - "id" : "office_tower_", - "name" : "Office Tower", - "sym" : 84, - "color" : "white", - "see_cost" : 5, - "mondensity" : 2, - "sidewalk" : true, - "_Building_Utility" : { - "cell_num" : { - "string_format" : { - "office_tower_%d" : [ - "id" - ] - } - } - } -} +[ + { + "type": "overmap_terrain", + "id": "office_tower_", + "name": "Office Tower", + "sym": 84, + "color": "white", + "see_cost": 5, + "mondensity": 2, + "sidewalk": true, + "_Building_Utility": { "cell_num": { "string_format": { "office_tower_%d": [ "id" ] } } } + } +] diff --git a/utilities/building-utility/Examples/output_office_template.json b/utilities/building-utility/Examples/output_office_template.json index afd655c0584f9..74632d67ac7a5 100644 --- a/utilities/building-utility/Examples/output_office_template.json +++ b/utilities/building-utility/Examples/output_office_template.json @@ -1,1506 +1,1506 @@ [ - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~|--------------------", - "~~~|,_____,_____,_____,s", - "~~~|,_____,_____,_____,s", - "~~~|,_____,_____,_____,s", - "~~~|,_____,_____,_____,s", - "~~~|,_____,_____,_____,s", - "~~~|,_____,_____,_____,s", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|___,,___,____,____,s", - "~~~|__,,,,__,____,____,s", - "~~~|___,,___,____,____,s", - "~~~|___,,___,____,____,s", - "~~~|________,____,____,s", - "~~~|________,____,____,s", - "~~~|________|---|---|HHG", - "~~~|________|.R<|EEE|...", - "~~~|________|.R.|EEED..." - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_1", - "type": "mapgen", - "weight": 250 + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~|--------------------", + "~~~|,_____,_____,_____,s", + "~~~|,_____,_____,_____,s", + "~~~|,_____,_____,_____,s", + "~~~|,_____,_____,_____,s", + "~~~|,_____,_____,_____,s", + "~~~|,_____,_____,_____,s", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|___,,___,____,____,s", + "~~~|__,,,,__,____,____,s", + "~~~|___,,___,____,____,s", + "~~~|___,,___,____,____,s", + "~~~|________,____,____,s", + "~~~|________,____,____,s", + "~~~|________|---|---|HHG", + "~~~|________|.R<|EEE|...", + "~~~|________|.R.|EEED..." + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "--------------------|~~~", - "s,_____,_____,_____,|~~~", - "s,_____,_____,_____,|~~~", - "s,_____,_____,_____,|~~~", - "s,_____,_____,_____,|~~~", - "s,_____,_____,_____,|~~~", - "s,_____,_____,_____,|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "s,____,____,________|~~~", - "s,____,____,________|~~~", - "s,____,____,________|~~~", - "s,____,____,________|~~~", - "s,____,____,________|~~~", - "s,____,____,________|~~~", - "GHH|---|---|________|~~~", - "...|xEE|.R<|________|~~~", - "...DEEE|.R.|___,,___|~~~" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_2", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_1", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "--------------------|~~~", + "s,_____,_____,_____,|~~~", + "s,_____,_____,_____,|~~~", + "s,_____,_____,_____,|~~~", + "s,_____,_____,_____,|~~~", + "s,_____,_____,_____,|~~~", + "s,_____,_____,_____,|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "s,____,____,________|~~~", + "s,____,____,________|~~~", + "s,____,____,________|~~~", + "s,____,____,________|~~~", + "s,____,____,________|~~~", + "s,____,____,________|~~~", + "GHH|---|---|________|~~~", + "...|xEE|.R<|________|~~~", + "...DEEE|.R.|___,,___|~~~" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "~~~|________|...|EEED...", - "~~~|________|...|EEx|...", - "~~~|________|-+-|---|HHG", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|____________________", - "~~~|____,,______,,______", - "~~~|___,,,,_____,,______", - "~~~|____,,_____,,,,__xs_", - "~~~|____,,______,,___ss_", - "~~~|-|XXXXXX||XXXXXX|---", - "~~~|~|EEEEEE||EEEEEE|~~~", - "~~~|||EEEEEE||EEEEEE|~~~", - "~~~||xEEEEEE||EEEEEE||~~", - "~~~|||EEEEEE||EEEEEEx|~~", - "~~~|~|EEEEEE||EEEEEE||~~", - "~~~|~|EEEEEE||EEEEEE|~~~", - "~~~|~|------||------|~~~", - "~~~|--------------------", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_3", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_2", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "~~~|________|...|EEED...", + "~~~|________|...|EEx|...", + "~~~|________|-+-|---|HHG", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|____________________", + "~~~|____,,______,,______", + "~~~|___,,,,_____,,______", + "~~~|____,,_____,,,,__xs_", + "~~~|____,,______,,___ss_", + "~~~|-|XXXXXX||XXXXXX|---", + "~~~|~|EEEEEE||EEEEEE|~~~", + "~~~|||EEEEEE||EEEEEE|~~~", + "~~~||xEEEEEE||EEEEEE||~~", + "~~~|||EEEEEE||EEEEEEx|~~", + "~~~|~|EEEEEE||EEEEEE||~~", + "~~~|~|EEEEEE||EEEEEE|~~~", + "~~~|~|------||------|~~~", + "~~~|--------------------", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "...DEEE|...|___,,___|~~~", - "...|EEE|...|__,,,,__|~~~", - "GHH|---|-+-|___,,___|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "____________________|~~~", - "|___________________|~~~", - "|___________________|~~~", - "|,_____,_____,_____,|~~~", - "|,_____,_____,_____,|~~~", - "|,_____,_____,_____,|~~~", - "|,_____,_____,_____,|~~~", - "|,_____,_____,_____,|~~~", - "|,_____,_____,_____,|~~~", - "|-------------------|~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_4", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_3", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "...DEEE|...|___,,___|~~~", + "...|EEE|...|__,,,,__|~~~", + "GHH|---|-+-|___,,___|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "____________________|~~~", + "|___________________|~~~", + "|___________________|~~~", + "|,_____,_____,_____,|~~~", + "|,_____,_____,_____,|~~~", + "|,_____,_____,_____,|~~~", + "|,_____,_____,_____,|~~~", + "|,_____,_____,_____,|~~~", + "|,_____,_____,_____,|~~~", + "|-------------------|~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~", + "~~~~~~~~~~~~~~~~~~~~~~~~" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "ssssssssssssssssssssssss", - "ssssssssssssssssssssssss", - "ss ", - "ss%%%%%%%%%%%%%%%%%%%%%%", - "ss%|-HH-|-HH-|-HH-|HH|--", - "ss%Vdcxl|dxdl|lddx|..|.S", - "ss%Vdh..|dh..|..hd|..+..", - "ss%|-..-|-..-|-..-|..|--", - "ss%V.................|.T", - "ss%V.................|..", - "ss%|-..-|-..-|-..-|..|--", - "ss%V.h..|..hd|..hd|..|..", - "ss%Vdxdl|^dxd|.xdd|..G..", - "ss%|----|----|----|..G..", - "ss%|llll|..hnnh......|..", - "ss%V.................|..", - "ss%V.ddd..........|+-|..", - "ss%|..hd|.hh.ceocc|.l|..", - "ss%|----|---------|--|..", - "ss%Vcdcl|...............", - "ss%V.h..+...............", - "ss%V...^|...|---|---|...", - "ss%|----|...||EEE|...", - "ss%|rrrr|...|.R.|EEED..." - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_5", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_4", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "ssssssssssssssssssssssss", + "ssssssssssssssssssssssss", + "ss ", + "ss%%%%%%%%%%%%%%%%%%%%%%", + "ss%|-HH-|-HH-|-HH-|HH|--", + "ss%Vdcxl|dxdl|lddx|..|.S", + "ss%Vdh..|dh..|..hd|..+..", + "ss%|-..-|-..-|-..-|..|--", + "ss%V.................|.T", + "ss%V.................|..", + "ss%|-..-|-..-|-..-|..|--", + "ss%V.h..|..hd|..hd|..|..", + "ss%Vdxdl|^dxd|.xdd|..G..", + "ss%|----|----|----|..G..", + "ss%|llll|..hnnh......|..", + "ss%V.................|..", + "ss%V.ddd..........|+-|..", + "ss%|..hd|.hh.ceocc|.l|..", + "ss%|----|---------|--|..", + "ss%Vcdcl|...............", + "ss%V.h..+...............", + "ss%V...^|...|---|---|...", + "ss%|----|...||EEE|...", + "ss%|rrrr|...|.R.|EEED..." + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "ssssssssssssssssssssssss", - "ssssssssssssssssssssssss", - " ss", - "%%%%%%%%%%%%%%%%%%%%%%ss", - "--|---|--HHHH-HHHH--|%ss", - ".T|..l|............^|%ss", - "..|-+-|...hhhhhhh...V%ss", - "--|...G...nnnnnnn...V%ss", - ".S|...G...nnnnnnn...V%ss", - "..+...|...hhhhhhh...V%ss", - "--|...|.............|%ss", - "..|...|-------------|%ss", - "..G....|l.......dxd^|%ss", - "..G....G...h....dh..V%ss", - "..|....|............V%ss", - "..|....|------|llccc|%ss", - "..|...........|-----|%ss", - "..|...........|...ddV%ss", - "..|----|---|......hdV%ss", - ".......+...|..|l...dV%ss", - ".......|rrr|..|-----|%ss", - "...|---|---|..|l.dddV%ss", - "...|xEE||......hdV%ss", - "...DEEE|.R.|..|.....V%ss" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_6", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_5", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "ssssssssssssssssssssssss", + "ssssssssssssssssssssssss", + " ss", + "%%%%%%%%%%%%%%%%%%%%%%ss", + "--|---|--HHHH-HHHH--|%ss", + ".T|..l|............^|%ss", + "..|-+-|...hhhhhhh...V%ss", + "--|...G...nnnnnnn...V%ss", + ".S|...G...nnnnnnn...V%ss", + "..+...|...hhhhhhh...V%ss", + "--|...|.............|%ss", + "..|...|-------------|%ss", + "..G....|l.......dxd^|%ss", + "..G....G...h....dh..V%ss", + "..|....|............V%ss", + "..|....|------|llccc|%ss", + "..|...........|-----|%ss", + "..|...........|...ddV%ss", + "..|----|---|......hdV%ss", + ".......+...|..|l...dV%ss", + ".......|rrr|..|-----|%ss", + "...|---|---|..|l.dddV%ss", + "...|xEE||......hdV%ss", + "...DEEE|.R.|..|.....V%ss" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "ss%|....+...|...|EEED...", - "ss%|----|...|...|EEx|...", - "ss%Vcdc^|...|-+-|---|...", - "ss%Vch..+...............", - "ss%V....|...............", - "ss%|----|-|-+--ccc--|...", - "ss%|..C..C|.....h..r|-+-", - "sss=......+..h.....r|...", - "ss%|r..CC.|.ddd....r|T.S", - "ss%|------|---------|---", - "ss%|~~~~~~~~~~~~~~~~~~~~", - "ss%|~|------||------|~~~", - "ss%|~|EEEEEE||EEEEEE|~~~", - "ss%|||EEEEEE||EEEEEE|~~~", - "ss%||xEEEEEE||EEEEEE||~~", - "ss%|||EEEEEE||EEEEEEx|~~", - "ss%|~|EEEEEE||EEEEEE||~~", - "ss%|~|EEEEEE||EEEEEE|~~~", - "ss%|~|XXXXXX||XXXXXX|~~~", - "ss%|-|__,,__||__,,__|---", - "ss%% x_,,,,_ __,,__ %%", - "ss __,,__ _,,,,_ ", - "ssssss__,,__ss__,,__ssss", - "ssssss______ss______ssss" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_7", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_6", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "ss%|....+...|...|EEED...", + "ss%|----|...|...|EEx|...", + "ss%Vcdc^|...|-+-|---|...", + "ss%Vch..+...............", + "ss%V....|...............", + "ss%|----|-|-+--ccc--|...", + "ss%|..C..C|.....h..r|-+-", + "sss=......+..h.....r|...", + "ss%|r..CC.|.ddd....r|T.S", + "ss%|------|---------|---", + "ss%|~~~~~~~~~~~~~~~~~~~~", + "ss%|~|------||------|~~~", + "ss%|~|EEEEEE||EEEEEE|~~~", + "ss%|||EEEEEE||EEEEEE|~~~", + "ss%||xEEEEEE||EEEEEE||~~", + "ss%|||EEEEEE||EEEEEEx|~~", + "ss%|~|EEEEEE||EEEEEE||~~", + "ss%|~|EEEEEE||EEEEEE|~~~", + "ss%|~|XXXXXX||XXXXXX|~~~", + "ss%|-|__,,__||__,,__|---", + "ss%% x_,,,,_ __,,__ %%", + "ss __,,__ _,,,,_ ", + "ssssss__,,__ss__,,__ssss", + "ssssss______ss______ssss" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "...DEEE|...|..|-----|%ss", - "...|EEE|...|..|^...lV%ss", - "...|---|-+-|......hdV%ss", - "...........G..|..dddV%ss", - "...........G..|-----|%ss", - ".......|---|..|...ddV%ss", - "|+-|...|...+......hdV%ss", - "|.l|...|rr.|.^|l...dV%ss", - "|--|...|---|--|-----|%ss", - "|...........c.......V%ss", - "|.......cxh.c.bbbbb.Vsss", - "|.......ccccc.......Gsss", - "|...................Gsss", - "|...................Vsss", - "|b..................Gsss", - "|b..................Gsss", - "|b..................Vsss", - "|b............bbbbb.V%ss", - "|...................|%ss", - "--HHHHHGGHHGGHHHHH--|%ss", - "%%%%% ssssssss %%%%%%%ss", - " ssssssss ss", - "ssssssssssssssssssssssss", - "ssssssssssssssssssssssss" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_8", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_7", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "...DEEE|...|..|-----|%ss", + "...|EEE|...|..|^...lV%ss", + "...|---|-+-|......hdV%ss", + "...........G..|..dddV%ss", + "...........G..|-----|%ss", + ".......|---|..|...ddV%ss", + "|+-|...|...+......hdV%ss", + "|.l|...|rr.|.^|l...dV%ss", + "|--|...|---|--|-----|%ss", + "|...........c.......V%ss", + "|.......cxh.c.bbbbb.Vsss", + "|.......ccccc.......Gsss", + "|...................Gsss", + "|...................Vsss", + "|b..................Gsss", + "|b..................Gsss", + "|b..................Vsss", + "|b............bbbbb.V%ss", + "|...................|%ss", + "--HHHHHGGHHGGHHHHH--|%ss", + "%%%%% ssssssss %%%%%%%ss", + " ssssssss ss", + "ssssssssssssssssssssssss", + "ssssssssssssssssssssssss" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "///|-HHH-HHH-HHH--|HHHH|", - "///|^.........^ll^V....|", - "///V...x.hx..x....V..hd|", - "///V..hd..d.hd....V.ddx|", - "///V...d..d..d....G....|", - "///|..............V....|", - "///V..............Vllll|", - "///V...x..x..x....|----|", - "///V...d..d.hd....|.....", - "///|..hd..d..d....|...ch", - "///V..............|^..cc", - "///V....................", - "///V...x................", - "///|..hd....|--|--|-HH-G", - "///|l..d....|ST|..|.....", - "///|----|...+..|..+.....", - "///|rrCC|...|..|..|.....", - "///|....+...|--||-|-|...", - "///|rr..|...|>R<|EEE|...", - "///|----|...|.R.|EEED..." - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_9", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_8", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "///|-HHH-HHH-HHH--|HHHH|", + "///|^.........^ll^V....|", + "///V...x.hx..x....V..hd|", + "///V..hd..d.hd....V.ddx|", + "///V...d..d..d....G....|", + "///|..............V....|", + "///V..............Vllll|", + "///V...x..x..x....|----|", + "///V...d..d.hd....|.....", + "///|..hd..d..d....|...ch", + "///V..............|^..cc", + "///V....................", + "///V...x................", + "///|..hd....|--|--|-HH-G", + "///|l..d....|ST|..|.....", + "///|----|...+..|..+.....", + "///|rrCC|...|..|..|.....", + "///|....+...|--||-|-|...", + "///|rr..|...|>R<|EEE|...", + "///|----|...|.R.|EEED..." + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "HHHHH|--HHH-HHH-HHH-|///", - ".....Vll........h..^|///", - ".h.c.V.....h........V///", - "xccc.V....ddx..ddx..V///", - ".....G..............V///", - "..h..V.....h...h....|///", - "^...^V....ddx..ddx..V///", - "-----|.....h........V///", - ".....|..........h...V///", - ".c...|....ddx..ddx..|///", - "xc..^|..............V///", - "................h...V///", - "...............ddx..V///", - "G-HH-|--|--|........|///", - ".....|..|TS|.......^|///", - ".....+..|..+...|----|///", - ".....|..|..|...|..CC|///", - "...|-|-||--|...+....|///", - "...|xEE|>R.|...|rrrr|///", - "...DEEE|.R.|...|----|///" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_10", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_9", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "HHHHH|--HHH-HHH-HHH-|///", + ".....Vll........h..^|///", + ".h.c.V.....h........V///", + "xccc.V....ddx..ddx..V///", + ".....G..............V///", + "..h..V.....h...h....|///", + "^...^V....ddx..ddx..V///", + "-----|.....h........V///", + ".....|..........h...V///", + ".c...|....ddx..ddx..|///", + "xc..^|..............V///", + "................h...V///", + "...............ddx..V///", + "G-HH-|--|--|........|///", + ".....|..|TS|.......^|///", + ".....+..|..+...|----|///", + ".....|..|..|...|..CC|///", + "...|-|-||--|...+....|///", + "...|xEE|>R.|...|rrrr|///", + "...DEEE|.R.|...|----|///" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "///|....+...|...|EEED...", - "///|T.S.|...+...|EEx|...", - "///|----|...|---|-|-|...", - "///|lll.....Vdd..l|.....", - "///V....c...Vdh..r|.....", - "///V..h.c...Vx....|^....", - "///|ccc6c...|-HGH-|-HHHH", - "///V....................", - "///V....................", - "///V....................", - "///|.ddx..ddx..ddx|-HHHG", - "///V..h....h....h.|.....", - "///V..............|.....", - "///V.ddx..ddx..ddx|.hnn.", - "///|........h..h..|.hnn.", - "///V..h...........|.hnnn", - "///V.ddx..ddx..ddx|.hnnn", - "///V..h....h......|...hh", - "///|............h.|.....", - "///|-HHH-HHHH-HHH-|-HHHH", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_11", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_10", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "///|....+...|...|EEED...", + "///|T.S.|...+...|EEx|...", + "///|----|...|---|-|-|...", + "///|lll.....Vdd..l|.....", + "///V....c...Vdh..r|.....", + "///V..h.c...Vx....|^....", + "///|ccc6c...|-HGH-|-HHHH", + "///V....................", + "///V....................", + "///V....................", + "///|.ddx..ddx..ddx|-HHHG", + "///V..h....h....h.|.....", + "///V..............|.....", + "///V.ddx..ddx..ddx|.hnn.", + "///|........h..h..|.hnn.", + "///V..h...........|.hnnn", + "///V.ddx..ddx..ddx|.hnnn", + "///V..h....h......|...hh", + "///|............h.|.....", + "///|-HHH-HHHH-HHH-|-HHHH", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "...DEEE|...|...+....|///", - "...|EEE|...+...|.S.T|///", - "...|-|-|---|...|----|///", - ".....|c..rrV......ll|///", - ".....|ch...+...c....V///", - "....^|ddd..V...6h...V///", - "HHHH-|-HHH-|...ccccc|///", - "....................V///", - "....................V///", - "....................V///", - "GHHH-|----|GG|--++--|///", - ".....|ccSe|..|^....^V///", - ".....|....|..|......V///", - ".nnh.|.......|..ddxdV///", - ".nnh.|.......|....hdV///", - "nnnh.|hh...hh|l.....V///", - "nnnh.|nn...nn|-+----|///", - "hh...|nn...nn|r..H.l|///", - ".....|hh...hh|r....l|///", - "HHHH-|-HHHHH-|--HHH-|///", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_12", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_11", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "...DEEE|...|...+....|///", + "...|EEE|...+...|.S.T|///", + "...|-|-|---|...|----|///", + ".....|c..rrV......ll|///", + ".....|ch...+...c....V///", + "....^|ddd..V...6h...V///", + "HHHH-|-HHH-|...ccccc|///", + "....................V///", + "....................V///", + "....................V///", + "GHHH-|----|GG|--++--|///", + ".....|ccSe|..|^....^V///", + ".....|....|..|......V///", + ".nnh.|.......|..ddxdV///", + ".nnh.|.......|....hdV///", + "nnnh.|hh...hh|l.....V///", + "nnnh.|nn...nn|-+----|///", + "hh...|nn...nn|r..H.l|///", + ".....|hh...hh|r....l|///", + "HHHH-|-HHHHH-|--HHH-|///", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssss|---|sssssss", - "///sssssssss|.R>|sssssss", - "///sssssssss|.R.|sssssss" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_13", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_12", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssss|---|sssssss", + "///sssssssss|.R>|sssssss", + "///sssssssss|.R.|sssssss" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_14", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_13", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "///sssssssss|...|sssssss", - "///sssssssss|...|sssssss", - "///sssssssss|-+-|sssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "///sssssssssssssssssssss", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_15", - "type": "mapgen", - "weight": 250 + "om_terrain": "office_tower_14", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "///sssssssss|...|sssssss", + "///sssssssss|...|sssssss", + "///sssssssss|-+-|sssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "///sssssssssssssssssssss", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } }, - { - "method": "json", - "object": { - "fill_ter": "t_floor", - "furniture": { - "@": "f_bed", - "S": "f_sink", - "T": "f_toilet", - "U": "f_statue", - "^": "f_indoor_plant", - "b": "f_bench", - "c": "f_counter", - "d": "f_desk", - "h": "f_chair", - "l": "f_locker", - "n": "f_table", - "o": "f_bookcase", - "r": "f_rack", - "z": "f_crate_c" - }, - "rows": [ - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "sssssssssssssssssssss///", - "////////////////////////", - "////////////////////////", - "////////////////////////", - "////////////////////////" - ], - "terrain": { - " ": "t_dirt", - "%": "t_shrub", - ")": "t_wreckage", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_floor", - "/": "t_sky", - "2": "t_utility_light", - "<": "t_stairs_up", - ">": "t_stairs_down", - "@": "t_floor", - "D": "t_door_metal_c", - "E": "t_elevator", - "G": "t_door_glass_c", - "H": "t_wall_glass_h", - "I": "t_column", - "L": "t_floor", - "R": "t_railing_v", - "S": "t_floor", - "T": "t_floor", - "V": "t_wall_glass_v", - "X": "t_door_metal_locked", - "^": "t_floor", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_floor", - "d": "t_floor", - "h": "t_floor", - "k": "t_floor", - "l": "t_floor", - "n": "t_floor", - "o": "t_floor", - "p": "t_floor", - "r": "t_floor", - "s": "t_sidewalk", - "u": "t_floor", - "x": "t_console_broken", - "z": "t_floor", - "{": "t_rubble", - "}": "t_manhole_cover", - "~": "t_rock" - } - }, - "om_terrain": "office_tower_16", - "type": "mapgen", - "weight": 250 - } -] \ No newline at end of file + "om_terrain": "office_tower_15", + "type": "mapgen", + "weight": 250 + }, + { + "method": "json", + "object": { + "fill_ter": "t_floor", + "furniture": { + "@": "f_bed", + "S": "f_sink", + "T": "f_toilet", + "U": "f_statue", + "^": "f_indoor_plant", + "b": "f_bench", + "c": "f_counter", + "d": "f_desk", + "h": "f_chair", + "l": "f_locker", + "n": "f_table", + "o": "f_bookcase", + "r": "f_rack", + "z": "f_crate_c" + }, + "rows": [ + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "sssssssssssssssssssss///", + "////////////////////////", + "////////////////////////", + "////////////////////////", + "////////////////////////" + ], + "terrain": { + " ": "t_dirt", + "%": "t_shrub", + ")": "t_wreckage", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_floor", + "/": "t_sky", + "2": "t_utility_light", + "<": "t_stairs_up", + ">": "t_stairs_down", + "@": "t_floor", + "D": "t_door_metal_c", + "E": "t_elevator", + "G": "t_door_glass_c", + "H": "t_wall_glass_h", + "I": "t_column", + "L": "t_floor", + "R": "t_railing_v", + "S": "t_floor", + "T": "t_floor", + "V": "t_wall_glass_v", + "X": "t_door_metal_locked", + "^": "t_floor", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_floor", + "d": "t_floor", + "h": "t_floor", + "k": "t_floor", + "l": "t_floor", + "n": "t_floor", + "o": "t_floor", + "p": "t_floor", + "r": "t_floor", + "s": "t_sidewalk", + "u": "t_floor", + "x": "t_console_broken", + "z": "t_floor", + "{": "t_rubble", + "}": "t_manhole_cover", + "~": "t_rock" + } + }, + "om_terrain": "office_tower_16", + "type": "mapgen", + "weight": 250 + } +] diff --git a/utilities/building-utility/Examples/output_office_terrain_template.json b/utilities/building-utility/Examples/output_office_terrain_template.json index 14c03c09f799d..2926461dfd25e 100644 --- a/utilities/building-utility/Examples/output_office_terrain_template.json +++ b/utilities/building-utility/Examples/output_office_terrain_template.json @@ -1,162 +1,162 @@ [ - { - "color": "white", - "id": "office_tower_1", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_2", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_3", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_4", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_5", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_6", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_7", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_8", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_9", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_10", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_11", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_12", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_13", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_14", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_15", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - }, - { - "color": "white", - "id": "office_tower_16", - "mondensity": 2, - "name": "Office Tower", - "see_cost": 5, - "sidewalk": true, - "sym": 84, - "type": "overmap_terrain" - } -] \ No newline at end of file + { + "color": "white", + "id": "office_tower_1", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_2", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_3", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_4", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_5", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_6", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_7", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_8", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_9", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_10", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_11", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_12", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_13", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_14", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_15", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + }, + { + "color": "white", + "id": "office_tower_16", + "mondensity": 2, + "name": "Office Tower", + "see_cost": 5, + "sidewalk": true, + "sym": 84, + "type": "overmap_terrain" + } +] From 7f95644e84d9d4033b4015c6486121602fd4dca5 Mon Sep 17 00:00:00 2001 From: johnrdconnolly <59102789+johnrdconnolly@users.noreply.github.com> Date: Sun, 28 Jun 2020 09:34:49 -0700 Subject: [PATCH 12/41] add longest_side to landscaping.json tools --- data/json/items/tool/landscaping.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/data/json/items/tool/landscaping.json b/data/json/items/tool/landscaping.json index c665b19df71b9..670c8503c9137 100644 --- a/data/json/items/tool/landscaping.json +++ b/data/json/items/tool/landscaping.json @@ -7,6 +7,7 @@ "description": "This is a large stick, with the end carved into a broad blade for digging. It could be used to dig shallow pits, but not deep ones.", "weight": "1133 g", "volume": "1500 ml", + "longest_side": "90 cm", "price": 0, "price_postapoc": 0, "bashing": 8, @@ -24,6 +25,7 @@ "description": "A small, sharp gardening shovel, perfect for digging up grubs and worms.", "weight": "280 g", "volume": "500 ml", + "longest_side": "25 cm", "price": 20, "price_postapoc": 50, "to_hit": 1, @@ -41,6 +43,7 @@ "description": "This is a farming implement. You can use it to turn tillable land into a slow-to-cross pile of dirt, or dig a shallow pit.", "weight": "1088 g", "volume": "3500 ml", + "longest_side": "140 cm", "price": 2000, "price_postapoc": 250, "to_hit": 1, @@ -60,6 +63,7 @@ "description": "This is a flattened stone affixed to a stick. It works passably well as a shovel but really can't compare to a real shovel.", "weight": "1581 g", "volume": "4 L", + "longest_side": "90 cm", "price": 0, "price_postapoc": 0, "bashing": 15, @@ -108,8 +112,9 @@ "type": "TOOL", "name": { "str": "scythe" }, "description": "This is an old-fashioned farming tool used to cut tall grass. While it may be a giant blade on the end of a stick, it is incredibly awkward to use for anything but its intended purpose.", - "weight": "3013 g", + "weight": "2140 g", "volume": "3250 ml", + "longest_side": "140 cm", "price": 8000, "price_postapoc": 250, "to_hit": -6, @@ -127,8 +132,9 @@ "type": "TOOL", "name": { "str": "shovel" }, "description": "This is a digging tool. Use it to dig pits adjacent to your location.", - "weight": "1315 g", + "weight": "2032 g", "volume": "3500 ml", + "longest_side": "140 cm", "price": 2000, "price_postapoc": 250, "to_hit": 3, @@ -187,8 +193,9 @@ "type": "TOOL", "name": { "str": "sickle" }, "description": "This is an old-fashioned farming tool used to cut tall grass. While it may be a massive curved blade on a handle, it is incredibly awkward to use for anything but its intended purpose.", - "weight": "1432 g", + "weight": "907 g", "volume": "1250 ml", + "longest_side": "50 cm", "price": 3800, "price_postapoc": 250, "to_hit": -2, @@ -208,6 +215,7 @@ "description": "A cordless, double-sided, gasoline-powered hedge trimmer. A long line of sharp-edged teeth extends from the engine; turning the trimmer on will make them rapidly vibrate. The poor man's chainsaw as far as the zombies are concerned.", "weight": "4500 g", "volume": "2500 ml", + "longest_side": "100 cm", "price": 4000, "price_postapoc": 250, "to_hit": -1, From a01746c422e15eeeaca490636acd28d32494273b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Karlsson?= Date: Sun, 28 Jun 2020 19:19:15 +0200 Subject: [PATCH 13/41] Fix content list for sealed stomach --- data/json/recipes/other/containers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/recipes/other/containers.json b/data/json/recipes/other/containers.json index 6e3e135ef5672..309bd51aa766e 100644 --- a/data/json/recipes/other/containers.json +++ b/data/json/recipes/other/containers.json @@ -92,7 +92,7 @@ "components": [ [ [ "water", 5 ], [ "water_clean", 5 ] ], [ [ "stomach", 1 ], [ "hstomach", 1 ], [ "demihuman_stomach", 1 ] ], - [ [ "cordage_short", 2, "LIST" ], [ "filament", 50, "LIST" ] ] + [ [ "cordage_short", 2, "LIST" ], [ "filament", 100, "LIST" ] ] ] }, { From 1a6769da4e8eebe88e7d7b98fd519db805f72390 Mon Sep 17 00:00:00 2001 From: Kevin Granade Date: Sun, 28 Jun 2020 20:24:12 +0000 Subject: [PATCH 14/41] Map reference migration part seven --- src/item_location.cpp | 4 +- src/live_view.cpp | 4 +- src/magic.cpp | 7 +- src/map_field.cpp | 8 +- src/mapbuffer.cpp | 5 +- src/mattack_actors.cpp | 7 +- src/mission_companion.cpp | 5 +- src/npctalk_funcs.cpp | 7 +- src/overmap.cpp | 5 +- src/overmap_ui.cpp | 7 +- src/projectile.cpp | 10 +- src/sdltiles.cpp | 3 +- src/teleport.cpp | 7 +- src/vehicle_part.cpp | 5 +- src/vehicle_selector.cpp | 11 ++- tests/behavior_test.cpp | 12 +-- tests/crafting_test.cpp | 7 +- tests/creature_in_field_test.cpp | 10 +- tests/explosion_balance_test.cpp | 8 +- tests/map_test.cpp | 7 +- tests/monster_test.cpp | 6 +- tests/npc_talk_test.cpp | 154 ++++++++++++++++-------------- tests/vehicle_drag_test.cpp | 17 ++-- tests/vehicle_efficiency_test.cpp | 9 +- tests/vehicle_turrets_test.cpp | 11 ++- 25 files changed, 184 insertions(+), 152 deletions(-) diff --git a/src/item_location.cpp b/src/item_location.cpp index 313d4f0368e08..51a614767f147 100644 --- a/src/item_location.cpp +++ b/src/item_location.cpp @@ -186,7 +186,7 @@ class item_location::impl::item_on_map : public item_location::impl } std::string describe( const Character *ch ) const override { - std::string res = g->m.name( cur ); + std::string res = get_map().name( cur ); if( ch ) { res += std::string( " " ) += direction_suffix( ch->pos(), cur ); } @@ -666,7 +666,7 @@ void item_location::deserialize( JsonIn &js ) ptr.reset( new impl::item_on_map( pos, idx ) ); } else if( type == "vehicle" ) { - vehicle *const veh = veh_pointer_or_null( g->m.veh_at( pos ) ); + vehicle *const veh = veh_pointer_or_null( get_map().veh_at( pos ) ); int part = obj.get_int( "part" ); if( veh && part >= 0 && part < veh->part_count() ) { ptr.reset( new impl::item_on_vehicle( vehicle_cursor( *veh, part ), idx ) ); diff --git a/src/live_view.cpp b/src/live_view.cpp index ffa8dd666e224..b4748b0bcc0d6 100644 --- a/src/live_view.cpp +++ b/src/live_view.cpp @@ -47,7 +47,7 @@ void live_view::show( const tripoint &p ) const int max_height = TERMY / 2; const int line_limit = max_height - 2; - const visibility_variables &cache = g->m.get_visibility_variables_cache(); + const visibility_variables &cache = get_map().get_visibility_variables_cache(); int line_out = START_LINE; // HACK: using dummy window to get the window height without refreshing. win = catacurses::newwin( 1, width, point_zero ); @@ -60,7 +60,7 @@ void live_view::show( const tripoint &p ) } ); ui->on_redraw( [this]( const ui_adaptor & ) { werase( win ); - const visibility_variables &cache = g->m.get_visibility_variables_cache(); + const visibility_variables &cache = get_map().get_visibility_variables_cache(); int line_out = START_LINE; g->pre_print_all_tile_info( mouse_position, win, line_out, getmaxy( win ) - 2, cache ); draw_border( win ); diff --git a/src/magic.cpp b/src/magic.cpp index 116f265e473ee..3147ea802946d 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -939,11 +939,12 @@ void spell::create_field( const tripoint &at ) const return; } if( one_in( type->field_chance ) ) { - field_entry *field = g->m.get_field( at, *type->field ); + map &here = get_map(); + field_entry *field = here.get_field( at, *type->field ); if( field ) { field->set_field_intensity( field->get_field_intensity() + intensity ); } else { - g->m.add_field( at, *type->field, intensity, -duration_turns() ); + here.add_field( at, *type->field, intensity, -duration_turns() ); } } } @@ -1418,7 +1419,7 @@ void known_magic::forget_spell( const spell_id &sp ) } add_msg( m_bad, _( "All knowledge of %s leaves you." ), sp->name ); // TODO: add parameter for owner of known_magic for this function - g->events().send( g->u.getID(), sp->id ); + g->events().send( get_avatar().getID(), sp->id ); spellbook.erase( sp ); } diff --git a/src/map_field.cpp b/src/map_field.cpp index acbf6a2c32f0a..c0c7b22bc8085 100644 --- a/src/map_field.cpp +++ b/src/map_field.cpp @@ -254,7 +254,8 @@ void map::gas_spread_to( field_entry &cur, maptile &dst ) void map::spread_gas( field_entry &cur, const tripoint &p, int percent_spread, const time_duration &outdoor_age_speedup, scent_block &sblk ) { - const oter_id &cur_om_ter = overmap_buffer.ter( ms_to_omt_copy( g->m.getabs( p ) ) ); + map &here = get_map(); + const oter_id &cur_om_ter = overmap_buffer.ter( ms_to_omt_copy( here.getabs( p ) ) ); const bool sheltered = g->is_sheltered( p ); const int winddirection = g->weather.winddirection; const int windpower = get_local_windpower( g->weather.windspeed, cur_om_ter, p, winddirection, @@ -397,6 +398,7 @@ bool map::process_fields_in_submap( submap *const current_submap, // Just to avoid typing that long string for a temp value. field_entry *tmpfld = nullptr; + map &here = get_map(); tripoint thep; thep.z = submap.z; @@ -492,7 +494,7 @@ bool map::process_fields_in_submap( submap *const current_submap, if( curtype == fd_fire ) { cur.set_field_age( std::max( -24_hours, cur.get_field_age() ) ); // Entire objects for ter/frn for flags - const oter_id &cur_om_ter = overmap_buffer.ter( ms_to_omt_copy( g->m.getabs( p ) ) ); + const oter_id &cur_om_ter = overmap_buffer.ter( ms_to_omt_copy( here.getabs( p ) ) ); bool sheltered = g->is_sheltered( p ); int winddirection = g->weather.winddirection; int windpower = get_local_windpower( g->weather.windspeed, cur_om_ter, p, winddirection, @@ -983,7 +985,7 @@ bool map::process_fields_in_submap( submap *const current_submap, if( curtype == fd_fungal_haze ) { if( one_in( 10 - 2 * cur.get_field_intensity() ) ) { // Haze'd terrain - fungal_effects( *g, g->m ).spread_fungus( p ); + fungal_effects( *g, here ).spread_fungus( p ); } } diff --git a/src/mapbuffer.cpp b/src/mapbuffer.cpp index 1b5767266c300..68a2ce922ede6 100644 --- a/src/mapbuffer.cpp +++ b/src/mapbuffer.cpp @@ -109,8 +109,9 @@ void mapbuffer::save( bool delete_after_save ) int num_saved_submaps = 0; int num_total_submaps = submaps.size(); - const tripoint map_origin = sm_to_omt_copy( g->m.get_abs_sub() ); - const bool map_has_zlevels = g != nullptr && g->m.has_zlevels(); + map &here = get_map(); + const tripoint map_origin = sm_to_omt_copy( here.get_abs_sub() ); + const bool map_has_zlevels = g != nullptr && here.has_zlevels(); static_popup popup; diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index ccfade8908d19..c9c677ae2b864 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -83,8 +83,9 @@ bool leap_actor::call( monster &z ) const if( !allow_no_target && z.attack_target() == nullptr ) { return false; } + map &here = get_map(); std::multimap candidates; - for( const tripoint &candidate : g->m.points_in_radius( z.pos(), max_range ) ) { + for( const tripoint &candidate : here.points_in_radius( z.pos(), max_range ) ) { if( candidate == z.pos() ) { continue; } @@ -113,9 +114,9 @@ bool leap_actor::call( monster &z ) const } bool blocked_path = false; // check if monster has a clear path to the proposed point - std::vector line = g->m.find_clear_path( z.pos(), dest ); + std::vector line = here.find_clear_path( z.pos(), dest ); for( auto &i : line ) { - if( g->m.impassable( i ) ) { + if( here.impassable( i ) ) { blocked_path = true; break; } diff --git a/src/mission_companion.cpp b/src/mission_companion.cpp index 2a9c018310f06..0074e24485605 100644 --- a/src/mission_companion.cpp +++ b/src/mission_companion.cpp @@ -706,7 +706,7 @@ npc_ptr talk_function::individual_mission( const tripoint &omt_pos, } } if( comp->in_vehicle ) { - g->m.unboard_vehicle( comp->pos() ); + get_map().unboard_vehicle( comp->pos() ); } popup( "%s %s", comp->name, desc ); comp->set_companion_mission( omt_pos, role_id, miss_id ); @@ -1730,10 +1730,11 @@ void talk_function::companion_return( npc &comp ) comp.reset_companion_mission(); comp.companion_mission_time = calendar::before_time_starts; comp.companion_mission_time_ret = calendar::before_time_starts; + map &here = get_map(); for( size_t i = 0; i < comp.companion_mission_inv.size(); i++ ) { for( const auto &it : comp.companion_mission_inv.const_stack( i ) ) { if( !it.count_by_charges() || it.charges > 0 ) { - g->m.add_item_or_charges( g->u.pos(), it ); + here.add_item_or_charges( g->u.pos(), it ); } } } diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index 7a18b273e5543..4b4a773920587 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -823,12 +823,13 @@ void talk_function::stranger_neutral( npc &p ) void talk_function::drop_stolen_item( npc &p ) { + map &here = get_map(); for( auto &elem : g->u.inv_dump() ) { if( elem->is_old_owner( p ) ) { item to_drop = g->u.i_rem( elem ); to_drop.remove_old_owner(); to_drop.set_owner( p ); - g->m.add_item_or_charges( g->u.pos(), to_drop ); + here.add_item_or_charges( g->u.pos(), to_drop ); } } if( p.known_stolen_item ) { @@ -865,7 +866,7 @@ void talk_function::drop_weapon( npc &p ) if( p.is_hallucination() ) { return; } - g->m.add_item_or_charges( p.pos(), p.remove_weapon() ); + get_map().add_item_or_charges( p.pos(), p.remove_weapon() ); } void talk_function::player_weapon_away( npc &/*p*/ ) @@ -875,7 +876,7 @@ void talk_function::player_weapon_away( npc &/*p*/ ) void talk_function::player_weapon_drop( npc &/*p*/ ) { - g->m.add_item_or_charges( g->u.pos(), g->u.remove_weapon() ); + get_map().add_item_or_charges( g->u.pos(), g->u.remove_weapon() ); } void talk_function::lead_to_safety( npc &p ) diff --git a/src/overmap.cpp b/src/overmap.cpp index de10717fa1b4f..d64ef6cddd869 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1586,7 +1586,8 @@ bool overmap::generate_sub( const int z ) // but at this point we don't know requires_sub = true; } else if( oter_above == "mine_finale" ) { - for( auto &q : g->m.points_in_radius( p, 1, 0 ) ) { + map &here = get_map(); + for( auto &q : here.points_in_radius( p, 1, 0 ) ) { ter_set( q, oter_id( "spiral" ) ); } ter_set( p, oter_id( "spiral_hub" ) ); @@ -3273,7 +3274,7 @@ bool overmap::build_slimepit( const tripoint &origin, int s ) const oter_id slimepit( "slimepit" ); bool requires_sub = false; - for( auto p : g->m.points_in_radius( origin, s + origin.z + 1, 0 ) ) { + for( auto p : get_map().points_in_radius( origin, s + origin.z + 1, 0 ) ) { int dist = square_dist( origin.xy(), p.xy() ); if( one_in( 2 * dist ) ) { chip_rock( p ); diff --git a/src/overmap_ui.cpp b/src/overmap_ui.cpp index ca4f4fce1d3de..8468e86d9a50b 100644 --- a/src/overmap_ui.cpp +++ b/src/overmap_ui.cpp @@ -1540,7 +1540,8 @@ static tripoint display( const tripoint &orig, const draw_data_t &data = draw_da ptype.only_known_by_player = true; ptype.avoid_danger = true; bool in_vehicle = g->u.in_vehicle && g->u.controlling_vehicle; - const optional_vpart_position vp = g->m.veh_at( g->u.pos() ); + map &here = get_map(); + const optional_vpart_position vp = here.veh_at( g->u.pos() ); if( vp && in_vehicle ) { vehicle &veh = vp->vehicle(); if( veh.can_float() && veh.is_watercraft() && veh.is_in_water() ) { @@ -1553,7 +1554,7 @@ static tripoint display( const tripoint &orig, const draw_data_t &data = draw_da } else { const oter_id oter = overmap_buffer.ter( curs ); // going to or coming from a water tile - if( is_river_or_lake( oter ) || g->m.has_flag( "SWIMMABLE", g->u.pos() ) ) { + if( is_river_or_lake( oter ) || here.has_flag( "SWIMMABLE", g->u.pos() ) ) { ptype.amphibious = true; } } @@ -1569,7 +1570,7 @@ static tripoint display( const tripoint &orig, const draw_data_t &data = draw_da // renew the path incase of a leftover dangling path point g->u.omt_path = overmap_buffer.get_npc_path( player_omt_pos, curs, ptype ); if( g->u.in_vehicle && g->u.controlling_vehicle ) { - vehicle *player_veh = veh_pointer_or_null( g->m.veh_at( g->u.pos() ) ); + vehicle *player_veh = veh_pointer_or_null( here.veh_at( g->u.pos() ) ); player_veh->omt_path = g->u.omt_path; player_veh->is_autodriving = true; g->u.assign_activity( ACT_AUTODRIVE ); diff --git a/src/projectile.cpp b/src/projectile.cpp index 80aa0174c62f8..339a7cd845004 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -7,7 +7,6 @@ #include "ammo_effect.h" #include "explosion.h" -#include "game.h" #include "item.h" #include "map.h" #include "map_iterator.h" @@ -95,14 +94,15 @@ void projectile::unset_custom_explosion() void apply_ammo_effects( const tripoint &p, const std::set &effects ) { + map &here = get_map(); for( const ammo_effect &ae : ammo_effects::get_all() ) { if( effects.count( ae.id.str() ) > 0 ) { - for( auto &pt : g->m.points_in_radius( p, ae.aoe_radius, ae.aoe_radius_z ) ) { + for( auto &pt : here.points_in_radius( p, ae.aoe_radius, ae.aoe_radius_z ) ) { if( x_in_y( ae.aoe_chance, 100 ) ) { - const bool check_sees = !ae.aoe_check_sees || g->m.sees( p, pt, ae.aoe_check_sees_radius ); - const bool check_passable = !ae.aoe_check_passable || g->m.passable( pt ); + const bool check_sees = !ae.aoe_check_sees || here.sees( p, pt, ae.aoe_check_sees_radius ); + const bool check_passable = !ae.aoe_check_passable || here.passable( pt ); if( check_sees && check_passable ) { - g->m.add_field( pt, ae.aoe_field_type, rng( ae.aoe_intensity_min, ae.aoe_intensity_max ) ); + here.add_field( pt, ae.aoe_field_type, rng( ae.aoe_intensity_min, ae.aoe_intensity_max ) ); } } } diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp index 1d804bfeb9266..033ac1fe16bcb 100644 --- a/src/sdltiles.cpp +++ b/src/sdltiles.cpp @@ -2653,6 +2653,7 @@ static void CheckMessages() actions_remove.insert( ACTION_CYCLE_MOVE ); } + map &here = get_map(); // Check if we can perform one of our actions on nearby terrain. If so, // display that action at the top of the list. for( int dx = -1; dx <= 1; dx++ ) { @@ -2664,7 +2665,7 @@ static void CheckMessages() // Check if we're near a vehicle, if so, vehicle controls should be top. { - const optional_vpart_position vp = g->m.veh_at( pos ); + const optional_vpart_position vp = here.veh_at( pos ); vehicle *const veh = veh_pointer_or_null( vp ); if( veh ) { const int veh_part = vp ? vp->part_index() : -1; diff --git a/src/teleport.cpp b/src/teleport.cpp index 33b53823bf757..732bf41e5b8d8 100644 --- a/src/teleport.cpp +++ b/src/teleport.cpp @@ -35,6 +35,7 @@ bool teleport::teleport( Creature &critter, int min_distance, int max_distance, int tries = 0; tripoint origin = critter.pos(); tripoint new_pos = origin; + map &here = get_map(); //The teleportee is dimensionally anchored so nothing happens if( p && ( p->worn_with_flag( "DIMENSIONAL_ANCHOR" ) || p->has_effect_with_flag( "DIMENSIONAL_ANCHOR" ) ) ) { @@ -47,9 +48,9 @@ bool teleport::teleport( Creature &critter, int min_distance, int max_distance, new_pos.x = origin.x + rdistance * std::cos( rangle ); new_pos.y = origin.y + rdistance * std::sin( rangle ); tries++; - } while( g->m.impassable( new_pos ) && tries < 20 ); + } while( here.impassable( new_pos ) && tries < 20 ); //handles teleporting into solids. - if( g->m.impassable( new_pos ) ) { + if( here.impassable( new_pos ) ) { if( safe ) { if( c_is_u ) { add_msg( m_bad, _( "You cannot teleport safely." ) ); @@ -58,7 +59,7 @@ bool teleport::teleport( Creature &critter, int min_distance, int max_distance, } critter.apply_damage( nullptr, bodypart_id( "torso" ), 9999 ); if( c_is_u ) { - g->events().send( p->getID(), g->m.obstacle_name( new_pos ) ); + g->events().send( p->getID(), here.obstacle_name( new_pos ) ); add_msg( m_bad, _( "You die after teleporting into a solid." ) ); } critter.check_dead_state(); diff --git a/src/vehicle_part.cpp b/src/vehicle_part.cpp index b680e819fe085..3cf10e0e41350 100644 --- a/src/vehicle_part.cpp +++ b/src/vehicle_part.cpp @@ -72,8 +72,9 @@ item vehicle_part::properties_to_item() const // Cables get special handling: their target coordinates need to remain // stored, and if a cable actually drops, it should be half-connected. if( tmp.has_flag( "CABLE_SPOOL" ) && !tmp.has_flag( "TOW_CABLE" ) ) { - const tripoint local_pos = g->m.getlocal( target.first ); - if( !g->m.veh_at( local_pos ) ) { + map &here = get_map(); + const tripoint local_pos = here.getlocal( target.first ); + if( !here.veh_at( local_pos ) ) { // That vehicle ain't there no more. tmp.item_tags.insert( "NO_DROP" ); } diff --git a/src/vehicle_selector.cpp b/src/vehicle_selector.cpp index 5536b16b0f96e..a1dcc3b14701c 100644 --- a/src/vehicle_selector.cpp +++ b/src/vehicle_selector.cpp @@ -3,7 +3,6 @@ #include #include -#include "game.h" #include "map.h" #include "optional.h" #include "point.h" @@ -12,10 +11,11 @@ vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool accessible, bool visibility_only ) { + map &here = get_map(); for( const tripoint &e : closest_tripoints_first( pos, radius ) ) { if( !accessible || - ( visibility_only ? g->m.sees( pos, e, radius ) : g->m.clear_path( pos, e, radius, 1, 100 ) ) ) { - if( const optional_vpart_position vp = g->m.veh_at( e ) ) { + ( visibility_only ? here.sees( pos, e, radius ) : here.clear_path( pos, e, radius, 1, 100 ) ) ) { + if( const optional_vpart_position vp = here.veh_at( e ) ) { data.emplace_back( vp->vehicle(), vp->part_index() ); } } @@ -25,9 +25,10 @@ vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool access vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool accessible, const vehicle &ignore ) { + map &here = get_map(); for( const tripoint &e : closest_tripoints_first( pos, radius ) ) { - if( !accessible || g->m.clear_path( pos, e, radius, 1, 100 ) ) { - if( const optional_vpart_position vp = g->m.veh_at( e ) ) { + if( !accessible || here.clear_path( pos, e, radius, 1, 100 ) ) { + if( const optional_vpart_position vp = here.veh_at( e ) ) { if( &vp->vehicle() != &ignore ) { data.emplace_back( vp->vehicle(), vp->part_index() ); } diff --git a/tests/behavior_test.cpp b/tests/behavior_test.cpp index 129d7cfdb9bb3..6f5a061af114f 100644 --- a/tests/behavior_test.cpp +++ b/tests/behavior_test.cpp @@ -6,7 +6,6 @@ #include "behavior_strategy.h" #include "catch/catch.hpp" #include "character_oracle.h" -#include "game.h" #include "item.h" #include "item_location.h" #include "map.h" @@ -149,7 +148,7 @@ TEST_CASE( "check_npc_behavior_tree", "[npc][behavior]" ) behavior::character_oracle_t oracle( &test_npc ); CHECK( npc_needs.tick( &oracle ) == "idle" ); SECTION( "Freezing" ) { - g->weather.temperature = 0; + get_weather().temperature = 0; test_npc.update_bodytemp(); CHECK( npc_needs.tick( &oracle ) == "idle" ); test_npc.worn.push_back( item( "backpack" ) ); @@ -187,6 +186,7 @@ TEST_CASE( "check_monster_behavior_tree", "[monster][behavior]" ) { const tripoint monster_location( 5, 5, 0 ); clear_map(); + map &here = get_map(); monster &test_monster = spawn_test_monster( "mon_locust", monster_location ); behavior::monster_oracle_t oracle( &test_monster ); @@ -197,14 +197,14 @@ TEST_CASE( "check_monster_behavior_tree", "[monster][behavior]" ) test_monster.reset_special( special_name ); } CHECK( monster_goals.tick( &oracle ) == "idle" ); - for( const tripoint &near_monster : g->m.points_in_radius( monster_location, 1 ) ) { - g->m.ter_set( near_monster, ter_id( "t_grass" ) ); - g->m.furn_set( near_monster, furn_id( "f_null" ) ); + for( const tripoint &near_monster : here.points_in_radius( monster_location, 1 ) ) { + here.ter_set( near_monster, ter_id( "t_grass" ) ); + here.furn_set( near_monster, furn_id( "f_null" ) ); } SECTION( "Special Attack" ) { test_monster.set_special( "EAT_CROP", 0 ); CHECK( monster_goals.tick( &oracle ) == "idle" ); - g->m.furn_set( monster_location, furn_id( "f_plant_seedling" ) ); + here.furn_set( monster_location, furn_id( "f_plant_seedling" ) ); CHECK( monster_goals.tick( &oracle ) == "EAT_CROP" ); test_monster.set_special( "EAT_CROP", 1 ); CHECK( monster_goals.tick( &oracle ) == "idle" ); diff --git a/tests/crafting_test.cpp b/tests/crafting_test.cpp index 6ade7cef7c72c..a7037d38c13c2 100644 --- a/tests/crafting_test.cpp +++ b/tests/crafting_test.cpp @@ -327,9 +327,10 @@ static void set_time( const time_point &time ) calendar::turn = time; g->reset_light_level(); int z = g->u.posz(); - g->m.update_visibility_cache( z ); - g->m.invalidate_map_cache( z ); - g->m.build_map_cache( z ); + map &here = get_map(); + here.update_visibility_cache( z ); + here.invalidate_map_cache( z ); + here.build_map_cache( z ); } // This tries to actually run the whole craft activity, which is more thorough, diff --git a/tests/creature_in_field_test.cpp b/tests/creature_in_field_test.cpp index 5d0106c496c18..4f9dc6fa1c76d 100644 --- a/tests/creature_in_field_test.cpp +++ b/tests/creature_in_field_test.cpp @@ -1,7 +1,6 @@ #include #include "catch/catch.hpp" -#include "game.h" #include "map.h" #include "map_helpers.h" #include "monster.h" @@ -12,22 +11,23 @@ TEST_CASE( "creature_in_field", "[monster],[field]" ) { static const tripoint target_location{ 5, 5, 0 }; clear_map(); + map &here = get_map(); GIVEN( "An acid field" ) { - g->m.add_field( target_location, field_type_id( "fd_acid" ) ); + here.add_field( target_location, field_type_id( "fd_acid" ) ); WHEN( "a monster stands on it" ) { monster &test_monster = spawn_test_monster( "mon_zombie", target_location ); REQUIRE( test_monster.get_hp() == test_monster.get_hp_max() ); THEN( "the monster takes damage" ) { - g->m.creature_in_field( test_monster ); + here.creature_in_field( test_monster ); CHECK( test_monster.get_hp() < test_monster.get_hp_max() ); } } WHEN( "A monster in a vehicle stands in it" ) { - g->m.add_vehicle( vproto_id( "handjack" ), target_location, 0 ); + here.add_vehicle( vproto_id( "handjack" ), target_location, 0 ); monster &test_monster = spawn_test_monster( "mon_zombie", target_location ); REQUIRE( test_monster.get_hp() == test_monster.get_hp_max() ); THEN( "the monster doesn't take damage" ) { - g->m.creature_in_field( test_monster ); + here.creature_in_field( test_monster ); CHECK( test_monster.get_hp() == test_monster.get_hp_max() ); } diff --git a/tests/explosion_balance_test.cpp b/tests/explosion_balance_test.cpp index a43089e836e59..12aade2b89328 100644 --- a/tests/explosion_balance_test.cpp +++ b/tests/explosion_balance_test.cpp @@ -59,7 +59,7 @@ static void check_lethality( const std::string &explosive_id, const int range, f // Set off an explosion item grenade( explosive_id ); grenade.charges = 0; - grenade.type->invoke( g->u, grenade, origin ); + grenade.type->invoke( get_avatar(), grenade, origin ); // see how many monsters survive std::vector survivors = g->get_creatures_if( []( const Creature & critter ) { return critter.is_monster(); @@ -111,10 +111,10 @@ static void check_vehicle_damage( const std::string &explosive_id, const std::st clear_map_and_put_player_underground(); tripoint origin( 30, 30, 0 ); - vehicle *target_vehicle = g->m.add_vehicle( vproto_id( vehicle_id ), origin, 0, -1, 0 ); + vehicle *target_vehicle = get_map().add_vehicle( vproto_id( vehicle_id ), origin, 0, -1, 0 ); std::vector before_hp = get_part_hp( target_vehicle ); - while( g->m.veh_at( origin ) ) { + while( get_map().veh_at( origin ) ) { origin.x++; } origin.x += range; @@ -122,7 +122,7 @@ static void check_vehicle_damage( const std::string &explosive_id, const std::st // Set off an explosion item grenade( explosive_id ); grenade.charges = 0; - grenade.type->invoke( g->u, grenade, origin ); + grenade.type->invoke( get_avatar(), grenade, origin ); std::vector after_hp = get_part_hp( target_vehicle ); diff --git a/tests/map_test.cpp b/tests/map_test.cpp index a4e04e191d7e6..cb3a919d8975e 100644 --- a/tests/map_test.cpp +++ b/tests/map_test.cpp @@ -16,12 +16,13 @@ TEST_CASE( "destroy_grabbed_furniture" ) clear_map(); GIVEN( "Furniture grabbed by the player" ) { const tripoint test_origin( 60, 60, 0 ); + map &here = get_map(); g->u.setpos( test_origin ); const tripoint grab_point = test_origin + tripoint_east; - g->m.furn_set( grab_point, furn_id( "f_chair" ) ); + here.furn_set( grab_point, furn_id( "f_chair" ) ); g->u.grab( object_type::FURNITURE, grab_point ); WHEN( "The furniture grabbed by the player is destroyed" ) { - g->m.destroy( grab_point ); + here.destroy( grab_point ); THEN( "The player's grab is released" ) { CHECK( g->u.get_grab_type() == object_type::NONE ); CHECK( g->u.grab_point == tripoint_zero ); @@ -86,5 +87,5 @@ TEST_CASE( "place_player_can_safely_move_multiple_submaps" ) // map::shift if the resulting shift exceeded a single submap, leading to a // broken active item cache. g->place_player( tripoint_zero ); - CHECK( g->m.check_submap_active_item_consistency().empty() ); + CHECK( get_map().check_submap_active_item_consistency().empty() ); } diff --git a/tests/monster_test.cpp b/tests/monster_test.cpp index 346f473536c57..dddceab3914d1 100644 --- a/tests/monster_test.cpp +++ b/tests/monster_test.cpp @@ -86,7 +86,7 @@ static int can_catch_player( const std::string &monster_type, const tripoint &di { clear_map(); REQUIRE( g->num_creatures() == 1 ); // the player - player &test_player = g->u; + player &test_player = get_avatar(); // Strip off any potentially encumbering clothing. std::list temp; while( test_player.takeoff( test_player.i_at( -2 ), &temp ) ) {} @@ -121,14 +121,14 @@ static int can_catch_player( const std::string &monster_type, const tripoint &di // Verify that only the player and one monster are present. REQUIRE( g->num_creatures() == 2 ); } - const int move_cost = g->m.combined_movecost( + const int move_cost = get_map().combined_movecost( test_player.pos(), test_player.pos() + direction_of_flight, nullptr, 0 ); tracker.push_back( {'p', move_cost, rl_dist( test_monster.pos(), test_player.pos() ), test_player.pos() } ); test_player.mod_moves( -move_cost ); } - g->m.clear_traps(); + get_map().clear_traps(); test_monster.set_dest( test_player.pos() ); test_monster.mod_moves( monster_speed ); while( test_monster.moves >= 0 ) { diff --git a/tests/npc_talk_test.cpp b/tests/npc_talk_test.cpp index f32cf30306219..f05b2e4f1f9e9 100644 --- a/tests/npc_talk_test.cpp +++ b/tests/npc_talk_test.cpp @@ -42,7 +42,7 @@ static const trait_id trait_PROF_SWAT( "PROF_SWAT" ); static npc &create_test_talker() { const string_id test_talker( "test_talker" ); - const character_id model_id = g->m.place_npc( point( 25, 25 ), test_talker, true ); + const character_id model_id = get_map().place_npc( point( 25, 25 ), test_talker, true ); g->load_npcs(); npc *model_npc = g->find_npc( model_id ); @@ -85,7 +85,7 @@ static std::string gen_dynamic_line( dialogue &d ) static void change_om_type( const std::string &new_type ) { - const tripoint omt_pos = ms_to_omt_copy( g->m.getabs( g->u.pos() ) ); + const tripoint omt_pos = ms_to_omt_copy( get_map().getabs( get_avatar().pos() ) ); overmap_buffer.ter_set( omt_pos, oter_id( new_type ) ); } @@ -93,16 +93,17 @@ static npc &prep_test( dialogue &d ) { clear_avatar(); clear_vehicles(); - REQUIRE_FALSE( g->u.in_vehicle ); + avatar &player_character = get_avatar(); + REQUIRE_FALSE( player_character.in_vehicle ); const tripoint test_origin( 15, 15, 0 ); - g->u.setpos( test_origin ); + player_character.setpos( test_origin ); g->faction_manager_ptr->create_if_needed(); npc &talker_npc = create_test_talker(); - d.alpha = &g->u; + d.alpha = &player_character; d.beta = &talker_npc; return talker_npc; @@ -133,10 +134,11 @@ TEST_CASE( "npc_talk_stats", "[npc_talk]" ) dialogue d; prep_test( d ); - g->u.str_cur = 8; - g->u.dex_cur = 8; - g->u.int_cur = 8; - g->u.per_cur = 8; + avatar &player_character = get_avatar(); + player_character.str_cur = 8; + player_character.dex_cur = 8; + player_character.int_cur = 8; + player_character.per_cur = 8; d.add_topic( "TALK_TEST_SIMPLE_STATS" ); gen_response_lines( d, 5 ); @@ -145,10 +147,10 @@ TEST_CASE( "npc_talk_stats", "[npc_talk]" ) CHECK( d.responses[2].text == "This is a dexterity test response." ); CHECK( d.responses[3].text == "This is an intelligence test response." ); CHECK( d.responses[4].text == "This is a perception test response." ); - g->u.str_cur = 6; - g->u.dex_cur = 6; - g->u.int_cur = 6; - g->u.per_cur = 6; + player_character.str_cur = 6; + player_character.dex_cur = 6; + player_character.int_cur = 6; + player_character.per_cur = 6; gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); @@ -168,14 +170,15 @@ TEST_CASE( "npc_talk_skills", "[npc_talk]" ) const skill_id skill( "driving" ); - g->u.set_skill_level( skill, 8 ); + avatar &player_character = get_avatar(); + player_character.set_skill_level( skill, 8 ); d.add_topic( "TALK_TEST_SIMPLE_SKILLS" ); gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a driving test response." ); - g->u.set_skill_level( skill, 6 ); + player_character.set_skill_level( skill, 6 ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); @@ -190,20 +193,21 @@ TEST_CASE( "npc_talk_wearing_and_trait", "[npc_talk]" ) dialogue d; npc &talker_npc = prep_test( d ); - for( const trait_id &tr : g->u.get_mutations() ) { - g->u.unset_mutation( tr ); + avatar &player_character = get_avatar(); + for( const trait_id &tr : player_character.get_mutations() ) { + player_character.unset_mutation( tr ); } d.add_topic( "TALK_TEST_WEARING_AND_TRAIT" ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.toggle_trait( trait_id( "ELFA_EARS" ) ); + player_character.toggle_trait( trait_id( "ELFA_EARS" ) ); gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a trait test response." ); CHECK( d.responses[2].text == "This is a short trait test response." ); - g->u.wear_item( item( "badge_marshal" ) ); + player_character.wear_item( item( "badge_marshal" ) ); gen_response_lines( d, 4 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a trait test response." ); @@ -217,16 +221,16 @@ TEST_CASE( "npc_talk_wearing_and_trait", "[npc_talk]" ) CHECK( d.responses[3].text == "This is a wearing test response." ); CHECK( d.responses[4].text == "This is a npc trait test response." ); CHECK( d.responses[5].text == "This is a npc short trait test response." ); - g->u.toggle_trait( trait_id( "ELFA_EARS" ) ); + player_character.toggle_trait( trait_id( "ELFA_EARS" ) ); talker_npc.toggle_trait( trait_id( "ELFA_EARS" ) ); - g->u.toggle_trait( trait_id( "PSYCHOPATH" ) ); + player_character.toggle_trait( trait_id( "PSYCHOPATH" ) ); talker_npc.toggle_trait( trait_id( "SAPIOVORE" ) ); gen_response_lines( d, 4 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a wearing test response." ); CHECK( d.responses[2].text == "This is a trait flags test response." ); CHECK( d.responses[3].text == "This is a npc trait flags test response." ); - g->u.toggle_trait( trait_id( "PSYCHOPATH" ) ); + player_character.toggle_trait( trait_id( "PSYCHOPATH" ) ); talker_npc.toggle_trait( trait_id( "SAPIOVORE" ) ); } @@ -234,6 +238,7 @@ TEST_CASE( "npc_talk_effect", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); d.add_topic( "TALK_TEST_EFFECT" ); gen_response_lines( d, 1 ); @@ -242,7 +247,7 @@ TEST_CASE( "npc_talk_effect", "[npc_talk]" ) gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an npc effect test response." ); - g->u.add_effect( effect_gave_quest_item, 9999_turns ); + player_character.add_effect( effect_gave_quest_item, 9999_turns ); d.gen_responses( d.topic_stack.back() ); gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); @@ -254,13 +259,14 @@ TEST_CASE( "npc_talk_service", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); d.add_topic( "TALK_TEST_SERVICE" ); - g->u.cash = 0; + player_character.cash = 0; talker_npc.add_effect( effect_currently_busy, 9999_turns ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.cash = 800; + player_character.cash = 800; gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a cash test response." ); @@ -460,25 +466,26 @@ TEST_CASE( "npc_talk_switch", "[npc_talk]" ) { dialogue d; prep_test( d ); + avatar &player_character = get_avatar(); d.add_topic( "TALK_TEST_SWITCH" ); - g->u.cash = 1000; + player_character.cash = 1000; gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an switch 1 test response." ); CHECK( d.responses[2].text == "This is another basic test response." ); - g->u.cash = 100; + player_character.cash = 100; gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an switch 2 test response." ); CHECK( d.responses[2].text == "This is another basic test response." ); - g->u.cash = 10; + player_character.cash = 10; gen_response_lines( d, 4 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an switch default 1 test response." ); CHECK( d.responses[2].text == "This is an switch default 2 test response." ); CHECK( d.responses[3].text == "This is another basic test response." ); - g->u.cash = 0; + player_character.cash = 0; gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an switch default 2 test response." ); @@ -489,13 +496,14 @@ TEST_CASE( "npc_talk_or", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); d.add_topic( "TALK_TEST_OR" ); - g->u.cash = 0; + player_character.cash = 0; talker_npc.add_effect( effect_currently_busy, 9999_turns ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.toggle_trait( trait_id( "ELFA_EARS" ) ); + player_character.toggle_trait( trait_id( "ELFA_EARS" ) ); gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is an or trait test response." ); @@ -505,12 +513,13 @@ TEST_CASE( "npc_talk_and", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); - g->u.toggle_trait( trait_id( "ELFA_EARS" ) ); + player_character.toggle_trait( trait_id( "ELFA_EARS" ) ); d.add_topic( "TALK_TEST_AND" ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.cash = 800; + player_character.cash = 800; talker_npc.remove_effect( effect_currently_busy ); gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); @@ -521,14 +530,15 @@ TEST_CASE( "npc_talk_nested", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); d.add_topic( "TALK_TEST_NESTED" ); talker_npc.add_effect( effect_currently_busy, 9999_turns ); - g->u.cash = 0; + player_character.cash = 0; gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.cash = 800; - g->u.int_cur = 11; + player_character.cash = 800; + player_character.int_cur = 11; gen_response_lines( d, 2 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a complex nested test response." ); @@ -537,8 +547,9 @@ TEST_CASE( "npc_talk_nested", "[npc_talk]" ) TEST_CASE( "npc_talk_conditionals", "[npc_talk]" ) { dialogue d; + avatar &player_character = get_avatar(); prep_test( d ); - g->u.cash = 800; + player_character.cash = 800; d.add_topic( "TALK_TEST_TRUE_FALSE_CONDITIONAL" ); gen_response_lines( d, 3 ); @@ -550,7 +561,7 @@ TEST_CASE( "npc_talk_conditionals", "[npc_talk]" ) CHECK( trial_success == true ); talk_effect_t &trial_effect = trial_success ? chosen.success : chosen.failure; CHECK( trial_effect.next_topic.id == "TALK_TEST_TRUE_CONDITION_NEXT" ); - g->u.cash = 0; + player_character.cash = 0; gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); CHECK( d.responses[1].text == "This is a true/false false response." ); @@ -566,8 +577,9 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); - g->u.remove_items_with( []( const item & it ) { + player_character.remove_items_with( []( const item & it ) { return it.get_category().get_id() == item_category_id( "books" ) || it.get_category().get_id() == item_category_id( "food" ) || it.typeId() == itype_id( "bottle_glass" ); @@ -590,17 +602,17 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) const auto has_beer_bottle = [&]( player & p, int count ) { return has_item( p, "bottle_glass", 1 ) && has_item( p, "beer", count ); }; - g->u.cash = 1000; - g->u.int_cur = 8; - g->u.worn.push_back( item( "backpack" ) ); + player_character.cash = 1000; + player_character.int_cur = 8; + player_character.worn.push_back( item( "backpack" ) ); d.add_topic( "TALK_TEST_EFFECTS" ); gen_response_lines( d, 19 ); // add and remove effect - REQUIRE_FALSE( g->u.has_effect( effect_infection ) ); + REQUIRE_FALSE( player_character.has_effect( effect_infection ) ); talk_effect_t &effects = d.responses[1].success; effects.apply( d ); - CHECK( g->u.has_effect( effect_infection ) ); - CHECK( g->u.get_effect_dur( effect_infection ) == time_duration::from_turns( 10 ) ); + CHECK( player_character.has_effect( effect_infection ) ); + CHECK( player_character.get_effect_dur( effect_infection ) == time_duration::from_turns( 10 ) ); REQUIRE_FALSE( talker_npc.has_effect( effect_infection ) ); effects = d.responses[2].success; effects.apply( d ); @@ -608,54 +620,54 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) CHECK( talker_npc.get_effect( effect_infection ).is_permanent() ); effects = d.responses[3].success; effects.apply( d ); - CHECK_FALSE( g->u.has_effect( effect_infection ) ); + CHECK_FALSE( player_character.has_effect( effect_infection ) ); effects = d.responses[4].success; effects.apply( d ); CHECK_FALSE( talker_npc.has_effect( effect_infection ) ); // add and remove trait - REQUIRE_FALSE( g->u.has_trait( trait_PROF_FED ) ); + REQUIRE_FALSE( player_character.has_trait( trait_PROF_FED ) ); effects = d.responses[5].success; effects.apply( d ); - CHECK( g->u.has_trait( trait_PROF_FED ) ); + CHECK( player_character.has_trait( trait_PROF_FED ) ); REQUIRE_FALSE( talker_npc.has_trait( trait_PROF_FED ) ); effects = d.responses[6].success; effects.apply( d ); CHECK( talker_npc.has_trait( trait_PROF_FED ) ); effects = d.responses[7].success; effects.apply( d ); - CHECK_FALSE( g->u.has_trait( trait_PROF_FED ) ); + CHECK_FALSE( player_character.has_trait( trait_PROF_FED ) ); effects = d.responses[8].success; effects.apply( d ); CHECK_FALSE( talker_npc.has_trait( trait_PROF_FED ) ); // buying and spending talker_npc.op_of_u.owed = 1000; - REQUIRE_FALSE( has_beer_bottle( g->u, 2 ) ); + REQUIRE_FALSE( has_beer_bottle( player_character, 2 ) ); REQUIRE( talker_npc.op_of_u.owed == 1000 ); effects = d.responses[9].success; effects.apply( d ); CHECK( talker_npc.op_of_u.owed == 500 ); - CHECK( has_beer_bottle( g->u, 2 ) ); - REQUIRE_FALSE( has_item( g->u, "bottle_plastic", 1 ) ); + CHECK( has_beer_bottle( player_character, 2 ) ); + REQUIRE_FALSE( has_item( player_character, "bottle_plastic", 1 ) ); effects = d.responses[10].success; effects.apply( d ); - CHECK( has_item( g->u, "bottle_plastic", 1 ) ); + CHECK( has_item( player_character, "bottle_plastic", 1 ) ); CHECK( talker_npc.op_of_u.owed == 500 ); effects = d.responses[11].success; effects.apply( d ); CHECK( talker_npc.op_of_u.owed == 0 ); talker_npc.op_of_u.owed = 1000; // effect chains - REQUIRE_FALSE( g->u.has_effect( effect_infected ) ); + REQUIRE_FALSE( player_character.has_effect( effect_infected ) ); REQUIRE_FALSE( talker_npc.has_effect( effect_infected ) ); - REQUIRE_FALSE( g->u.has_trait( trait_PROF_SWAT ) ); + REQUIRE_FALSE( player_character.has_trait( trait_PROF_SWAT ) ); REQUIRE_FALSE( talker_npc.has_trait( trait_PROF_SWAT ) ); effects = d.responses[12].success; effects.apply( d ); - CHECK( g->u.has_effect( effect_infected ) ); - CHECK( g->u.get_effect_dur( effect_infected ) == time_duration::from_turns( 10 ) ); + CHECK( player_character.has_effect( effect_infected ) ); + CHECK( player_character.get_effect_dur( effect_infected ) == time_duration::from_turns( 10 ) ); CHECK( talker_npc.has_effect( effect_infected ) ); CHECK( talker_npc.get_effect( effect_infected ).is_permanent() ); - CHECK( g->u.has_trait( trait_PROF_SWAT ) ); + CHECK( player_character.has_trait( trait_PROF_SWAT ) ); CHECK( talker_npc.has_trait( trait_PROF_SWAT ) ); CHECK( talker_npc.op_of_u.owed == 0 ); CHECK( talker_npc.get_attitude() == NPCATT_KILL ); @@ -707,17 +719,17 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) // test sell and consume d.add_topic( "TALK_TEST_EFFECTS" ); gen_response_lines( d, 19 ); - REQUIRE( has_item( g->u, "bottle_plastic", 1 ) ); - REQUIRE( has_beer_bottle( g->u, 2 ) ); - const std::vector glass_bottles = g->u.items_with( []( const item & it ) { + REQUIRE( has_item( player_character, "bottle_plastic", 1 ) ); + REQUIRE( has_beer_bottle( player_character, 2 ) ); + const std::vector glass_bottles = player_character.items_with( []( const item & it ) { return it.typeId() == itype_id( "bottle_glass" ); } ); REQUIRE( !glass_bottles.empty() ); - REQUIRE( g->u.wield( *glass_bottles.front() ) ); + REQUIRE( player_character.wield( *glass_bottles.front() ) ); effects = d.responses[14].success; effects.apply( d ); - CHECK_FALSE( has_item( g->u, "bottle_plastic", 1 ) ); - CHECK_FALSE( has_item( g->u, "beer", 1 ) ); + CHECK_FALSE( has_item( player_character, "bottle_plastic", 1 ) ); + CHECK_FALSE( has_item( player_character, "beer", 1 ) ); CHECK( has_item( talker_npc, "bottle_plastic", 1 ) ); CHECK( has_item( talker_npc, "beer", 2 ) ); effects = d.responses[15].success; @@ -726,11 +738,11 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) CHECK( has_item( talker_npc, "beer", 1 ) ); effects = d.responses[16].success; effects.apply( d ); - CHECK( has_item( g->u, "beer", 1 ) ); + CHECK( has_item( player_character, "beer", 1 ) ); effects = d.responses[17].success; effects.apply( d ); - CHECK( has_item( g->u, "beer", 0 ) ); - CHECK_FALSE( has_item( g->u, "beer", 1 ) ); + CHECK( has_item( player_character, "beer", 0 ) ); + CHECK_FALSE( has_item( player_character, "beer", 1 ) ); } TEST_CASE( "npc_talk_combat_commands", "[npc_talk]" ) @@ -848,13 +860,14 @@ TEST_CASE( "npc_talk_bionics", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); - g->u.clear_bionics(); + player_character.clear_bionics(); talker_npc.clear_bionics(); d.add_topic( "TALK_TEST_BIONICS" ); gen_response_lines( d, 1 ); CHECK( d.responses[0].text == "This is a basic test response." ); - g->u.add_bionic( bionic_id( "bio_ads" ) ); + player_character.add_bionic( bionic_id( "bio_ads" ) ); talker_npc.add_bionic( bionic_id( "bio_power_storage" ) ); gen_response_lines( d, 3 ); CHECK( d.responses[0].text == "This is a basic test response." ); @@ -866,9 +879,10 @@ TEST_CASE( "npc_talk_effects", "[npc_talk]" ) { dialogue d; npc &talker_npc = prep_test( d ); + avatar &player_character = get_avatar(); // speaker effects just use are owed because I don't want to do anything complicated - g->u.cash = 1000; + player_character.cash = 1000; talker_npc.op_of_u.owed = 2000; CHECK( talker_npc.op_of_u.owed == 2000 ); d.add_topic( "TALK_TEST_SPEAKER_EFFECT_SIMPLE" ); diff --git a/tests/vehicle_drag_test.cpp b/tests/vehicle_drag_test.cpp index d749fb75c1498..499b2eafc1ddb 100644 --- a/tests/vehicle_drag_test.cpp +++ b/tests/vehicle_drag_test.cpp @@ -7,7 +7,6 @@ #include "bodypart.h" #include "calendar.h" #include "catch/catch.hpp" -#include "game.h" #include "map.h" #include "map_helpers.h" #include "point.h" @@ -28,26 +27,28 @@ static void clear_game_drag( const ter_id &terrain ) clear_creatures(); clear_npcs(); + avatar &player_character = get_avatar(); // Move player somewhere safe - CHECK( !g->u.in_vehicle ); - g->u.setpos( tripoint_zero ); + CHECK( !player_character.in_vehicle ); + player_character.setpos( tripoint_zero ); // Blind the player to avoid needless drawing-related overhead - g->u.add_effect( effect_blind, 1_turns, num_bp, true ); + player_character.add_effect( effect_blind, 1_turns, num_bp, true ); // Make sure the ST is 8 so that muscle powered results are consistent - g->u.str_cur = 8; + player_character.str_cur = 8; build_test_map( terrain ); + map &here = get_map(); // hard force a rebuild of caches - g->m.shift( point_south ); - g->m.shift( point_north ); + here.shift( point_south ); + here.shift( point_north ); } static vehicle *setup_drag_test( const vproto_id &veh_id ) { clear_vehicles(); const tripoint map_starting_point( 60, 60, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( veh_id, map_starting_point, -90, 0, 0 ); + vehicle *veh_ptr = get_map().add_vehicle( veh_id, map_starting_point, -90, 0, 0 ); REQUIRE( veh_ptr != nullptr ); if( veh_ptr == nullptr ) { diff --git a/tests/vehicle_efficiency_test.cpp b/tests/vehicle_efficiency_test.cpp index 50437ff9686d0..87ceb1d9257bd 100644 --- a/tests/vehicle_efficiency_test.cpp +++ b/tests/vehicle_efficiency_test.cpp @@ -171,7 +171,8 @@ static int test_efficiency( const vproto_id &veh_id, int &expected_mass, clear_game( terrain ); const tripoint map_starting_point( 60, 60, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( veh_id, map_starting_point, -90, 0, 0 ); + map &here = get_map(); + vehicle *veh_ptr = here.add_vehicle( veh_id, map_starting_point, -90, 0, 0 ); REQUIRE( veh_ptr != nullptr ); if( veh_ptr == nullptr ) { @@ -221,18 +222,18 @@ static int test_efficiency( const vproto_id &veh_id, int &expected_mass, CHECK( veh.safe_velocity() > 0 ); while( veh.engine_on && veh.safe_velocity() > 0 && cycles_left > 0 ) { cycles_left--; - g->m.vehmove(); + here.vehmove(); veh.idle( true ); // If the vehicle starts skidding, the effects become random and test is RUINED REQUIRE( !veh.skidding ); for( const tripoint &pos : veh.get_points() ) { - REQUIRE( g->m.ter( pos ) ); + REQUIRE( here.ter( pos ) ); } // How much it moved tiles_travelled += square_dist( starting_point, veh.global_pos3() ); // Bring it back to starting point to prevent it from leaving the map const tripoint displacement = starting_point - veh.global_pos3(); - g->m.displace_vehicle( veh, displacement ); + here.displace_vehicle( veh, displacement ); if( reset_velocity_turn < 0 ) { continue; } diff --git a/tests/vehicle_turrets_test.cpp b/tests/vehicle_turrets_test.cpp index 8f8afb3d43083..6c319c9adf96d 100644 --- a/tests/vehicle_turrets_test.cpp +++ b/tests/vehicle_turrets_test.cpp @@ -7,7 +7,6 @@ #include "ammo.h" #include "avatar.h" #include "catch/catch.hpp" -#include "game.h" #include "item.h" #include "item_location.h" #include "itype.h" @@ -61,9 +60,11 @@ static const vpart_info *biggest_tank( const ammotype &ammo ) TEST_CASE( "vehicle_turret", "[vehicle] [gun] [magazine] [.]" ) { + map &here = get_map(); + avatar &player_character = get_avatar(); for( auto e : turret_types() ) { SECTION( e->name() ) { - vehicle *veh = g->m.add_vehicle( vproto_id( "none" ), point( 65, 65 ), 270, 0, 0 ); + vehicle *veh = here.add_vehicle( vproto_id( "none" ), point( 65, 65 ), 270, 0, 0 ); REQUIRE( veh ); const int idx = veh->install_part( point_zero, e->get_id(), true ); @@ -94,10 +95,10 @@ TEST_CASE( "vehicle_turret", "[vehicle] [gun] [magazine] [.]" ) REQUIRE( qry.query() == turret_data::status::ready ); REQUIRE( qry.range() > 0 ); - g->u.setpos( veh->global_part_pos3( idx ) ); - REQUIRE( qry.fire( g->u, g->u.pos() + point( qry.range(), 0 ) ) > 0 ); + player_character.setpos( veh->global_part_pos3( idx ) ); + REQUIRE( qry.fire( player_character, player_character.pos() + point( qry.range(), 0 ) ) > 0 ); - g->m.destroy_vehicle( veh ); + here.destroy_vehicle( veh ); } } } From 8185212260cc7c59086fa6fd4795f5aa0e6cb2df Mon Sep 17 00:00:00 2001 From: Kevin Granade Date: Sun, 28 Jun 2020 22:20:22 +0000 Subject: [PATCH 15/41] Map reference migration part eight --- src/item_pocket.cpp | 13 ++-- src/map.cpp | 4 +- src/panels.cpp | 32 ++++---- src/pixel_minimap.cpp | 26 +++---- src/sounds.cpp | 141 +++++++++++++++++++--------------- src/visitable.cpp | 14 ++-- tests/archery_damage_test.cpp | 12 +-- tests/modify_morale_test.cpp | 14 ++-- tests/projectile_test.cpp | 16 ++-- tests/vehicle_power_test.cpp | 22 +++--- tests/vehicle_test.cpp | 33 ++++---- 11 files changed, 177 insertions(+), 150 deletions(-) diff --git a/src/item_pocket.cpp b/src/item_pocket.cpp index 743197e547eaf..9312acb413b03 100644 --- a/src/item_pocket.cpp +++ b/src/item_pocket.cpp @@ -5,7 +5,6 @@ #include "cata_utility.h" #include "crafting.h" #include "enums.h" -#include "game.h" #include "generic_factory.h" #include "handle_liquid.h" #include "item.h" @@ -1052,6 +1051,7 @@ void item_pocket::overflow( const tripoint &pos ) // no items to overflow return; } + map &here = get_map(); // first remove items that shouldn't be in there anyway for( auto iter = contents.begin(); iter != contents.end(); ) { ret_val ret_contain = can_contain( *iter ); @@ -1059,7 +1059,7 @@ void item_pocket::overflow( const tripoint &pos ) ( !ret_contain.success() && ret_contain.value() != contain_code::ERR_NO_SPACE && ret_contain.value() != contain_code::ERR_CANNOT_SUPPORT ) ) { - g->m.add_item_or_charges( pos, *iter ); + here.add_item_or_charges( pos, *iter ); iter = contents.erase( iter ); } else { ++iter; @@ -1083,7 +1083,7 @@ void item_pocket::overflow( const tripoint &pos ) if( overflow_count > 0 ) { ammo.charges -= overflow_count; item dropped_ammo( ammo.typeId(), ammo.birthday(), overflow_count ); - g->m.add_item_or_charges( pos, contents.front() ); + here.add_item_or_charges( pos, contents.front() ); total_qty -= overflow_count; } if( ammo.count() == 0 ) { @@ -1102,7 +1102,7 @@ void item_pocket::overflow( const tripoint &pos ) return left.volume() > right.volume(); } ); while( remaining_volume() < 0_ml && !contents.empty() ) { - g->m.add_item_or_charges( pos, contents.front() ); + here.add_item_or_charges( pos, contents.front() ); contents.pop_front(); } } @@ -1111,7 +1111,7 @@ void item_pocket::overflow( const tripoint &pos ) return left.weight() > right.weight(); } ); while( remaining_weight() < 0_gram && !contents.empty() ) { - g->m.add_item_or_charges( pos, contents.front() ); + here.add_item_or_charges( pos, contents.front() ); contents.pop_front(); } } @@ -1133,8 +1133,9 @@ void item_pocket::on_contents_changed() bool item_pocket::spill_contents( const tripoint &pos ) { + map &here = get_map(); for( item &it : contents ) { - g->m.add_item_or_charges( pos, it ); + here.add_item_or_charges( pos, it ); } contents.clear(); diff --git a/src/map.cpp b/src/map.cpp index ce6bb11e60669..e9b3edbb1bad5 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3642,7 +3642,7 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) for( const ammo_effect &ae : ammo_effects::get_all() ) { if( ammo_effects.count( ae.id.str() ) > 0 ) { if( x_in_y( ae.trail_chance, 100 ) ) { - g->m.add_field( p, ae.trail_field_type, rng( ae.trail_intensity_min, ae.trail_intensity_max ) ); + add_field( p, ae.trail_field_type, rng( ae.trail_intensity_min, ae.trail_intensity_max ) ); } } } @@ -6951,7 +6951,7 @@ void map::produce_sap( const tripoint &p, const time_duration &time_since_last_a item sap( "maple_sap", calendar::turn ); - sap.set_item_temperature( temp_to_kelvin( g->m.get_temperature( p ) ) ); + sap.set_item_temperature( temp_to_kelvin( get_temperature( p ) ) ); // Is there a proper container? map_stack items = i_at( p ); diff --git a/src/panels.cpp b/src/panels.cpp index a981de8c666b2..459f366f047ec 100644 --- a/src/panels.cpp +++ b/src/panels.cpp @@ -388,8 +388,9 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const mvwputch( w_minimap, point( arrowx + start_x, arrowy + start_y ), c_red, glyph ); } } - - const int sight_points = g->u.overmap_sight_range( g->light_level( g->u.posz() ) ); + avatar &player_character = get_avatar(); + const int sight_points = player_character.overmap_sight_range( g->light_level( + player_character.posz() ) ); for( int i = -3; i <= 3; i++ ) { for( int j = -3; j <= 3; j++ ) { if( i > -3 && i < 3 && j > -3 && j < 3 ) { @@ -399,7 +400,7 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const int horde_size = overmap_buffer.get_horde_size( omp ); if( horde_size >= HORDE_VISIBILITY_SIZE ) { if( overmap_buffer.seen( omp ) - && g->u.overmap_los( omp, sight_points ) ) { + && player_character.overmap_los( omp, sight_points ) ) { mvwputch( w_minimap, point( i + 3, j + 3 ), c_green, horde_size > HORDE_VISIBILITY_SIZE * 2 ? 'Z' : 'z' ); } @@ -435,7 +436,7 @@ static std::string get_temp( const avatar &u ) std::string temp; if( u.has_item_with_flag( "THERMOMETER" ) || u.has_bionic( bionic_id( "bio_meteorologist" ) ) ) { - temp = print_temperature( g->weather.get_temperature( u.pos() ) ); + temp = print_temperature( get_weather().get_temperature( u.pos() ) ); } if( temp.empty() ) { return "-"; @@ -1335,11 +1336,12 @@ static void draw_loc_labels( const avatar &u, const catacurses::window &w, bool } else { // NOLINTNEXTLINE(cata-use-named-point-constants) mvwprintz( w, point( 1, 1 ), c_light_gray, _( "Sky :" ) ); - const weather_datum wdata = weather_data( g->weather.weather ); + const weather_datum wdata = weather_data( get_weather().weather ); wprintz( w, wdata.color, " %s", wdata.name ); } // display lighting - const auto ll = get_light_level( g->u.fine_detail_vision_mod() ); + const std::pair ll = get_light_level( + get_avatar().fine_detail_vision_mod() ); mvwprintz( w, point( 1, 2 ), c_light_gray, "%s ", _( "Light:" ) ); wprintz( w, ll.second, ll.first ); @@ -1505,7 +1507,8 @@ static void draw_env_compact( avatar &u, const catacurses::window &w ) mvwprintz( w, point( 8, 3 ), wdata.color, wdata.name ); } // display lighting - const auto ll = get_light_level( g->u.fine_detail_vision_mod() ); + const std::pair ll = get_light_level( + get_avatar().fine_detail_vision_mod() ); mvwprintz( w, point( 8, 4 ), ll.second, ll.first ); // wind const oter_id &cur_om_ter = overmap_buffer.ter( u.global_omt_location() ); @@ -1555,7 +1558,7 @@ static void draw_health_classic( avatar &u, const catacurses::window &w ) vehicle *veh = g->remoteveh(); if( veh == nullptr && u.in_vehicle ) { - veh = veh_pointer_or_null( g->m.veh_at( u.pos() ) ); + veh = veh_pointer_or_null( get_map().veh_at( u.pos() ) ); } werase( w ); @@ -1760,7 +1763,7 @@ static void draw_veh_compact( const avatar &u, const catacurses::window &w ) // vehicle display vehicle *veh = g->remoteveh(); if( veh == nullptr && u.in_vehicle ) { - veh = veh_pointer_or_null( g->m.veh_at( u.pos() ) ); + veh = veh_pointer_or_null( get_map().veh_at( u.pos() ) ); } if( veh ) { veh->print_fuel_indicators( w, point_zero ); @@ -1792,7 +1795,7 @@ static void draw_veh_padding( const avatar &u, const catacurses::window &w ) // vehicle display vehicle *veh = g->remoteveh(); if( veh == nullptr && u.in_vehicle ) { - veh = veh_pointer_or_null( g->m.veh_at( u.pos() ) ); + veh = veh_pointer_or_null( get_map().veh_at( u.pos() ) ); } if( veh ) { veh->print_fuel_indicators( w, point_east ); @@ -1847,7 +1850,7 @@ static void draw_weather_classic( avatar &, const catacurses::window &w ) if( g->get_levz() < 0 ) { mvwprintz( w, point_zero, c_light_gray, _( "Underground" ) ); } else { - const weather_datum wdata = weather_data( g->weather.weather ); + const weather_datum wdata = weather_data( get_weather().weather ); mvwprintz( w, point_zero, c_light_gray, _( "Weather :" ) ); mvwprintz( w, point( 10, 0 ), wdata.color, wdata.name ); } @@ -1862,7 +1865,8 @@ static void draw_lighting_classic( const avatar &u, const catacurses::window &w { werase( w ); - const auto ll = get_light_level( g->u.fine_detail_vision_mod() ); + const std::pair ll = get_light_level( + get_avatar().fine_detail_vision_mod() ); mvwprintz( w, point_zero, c_light_gray, _( "Lighting:" ) ); mvwprintz( w, point( 10, 0 ), ll.second, ll.first ); @@ -1915,7 +1919,7 @@ static void draw_time_classic( const avatar &u, const catacurses::window &w ) } if( u.has_item_with_flag( "THERMOMETER" ) || u.has_bionic( bionic_id( "bio_meteorologist" ) ) ) { - std::string temp = print_temperature( g->weather.get_temperature( u.pos() ) ); + std::string temp = print_temperature( get_weather().get_temperature( u.pos() ) ); mvwprintz( w, point( 31, 0 ), c_light_gray, _( "Temp : " ) + temp ); } @@ -1978,7 +1982,7 @@ static void draw_mana_wide( const player &u, const catacurses::window &w ) static bool spell_panel() { - return g->u.magic.knows_spell(); + return get_avatar().magic.knows_spell(); } bool default_render() diff --git a/src/pixel_minimap.cpp b/src/pixel_minimap.cpp index a98b1d3bfe376..e48725537c7d4 100644 --- a/src/pixel_minimap.cpp +++ b/src/pixel_minimap.cpp @@ -83,17 +83,16 @@ SDL_Texture_Ptr create_cache_texture( const SDL_Renderer_Ptr &renderer, int tile SDL_Color get_map_color_at( const tripoint &p ) { - const map &m = g->m; - - if( const auto vp = m.veh_at( p ) ) { + const map &here = get_map(); + if( const auto vp = here.veh_at( p ) ) { return curses_color_to_SDL( vp->vehicle().part_color( vp->part_index() ) ); } - if( const auto furn_id = m.furn( p ) ) { + if( const auto furn_id = here.furn( p ) ) { return curses_color_to_SDL( furn_id->color() ); } - return curses_color_to_SDL( m.ter( p )->color() ); + return curses_color_to_SDL( here.ter( p )->color() ); } SDL_Color get_critter_color( Creature *critter, int flicker, int mixture ) @@ -102,7 +101,7 @@ SDL_Color get_critter_color( Creature *critter, int flicker, int mixture ) if( const monster *m = dynamic_cast( critter ) ) { //faction status (attacking or tracking) determines if red highlights get applied to creature - const monster_attitude matt = m->attitude( &g->u ); + const monster_attitude matt = m->attitude( &get_avatar() ); if( MATT_ATTACK == matt || MATT_FOLLOW == matt ) { const SDL_Color red_pixel = SDL_Color{ 0xFF, 0x0, 0x0, 0xFF }; @@ -221,7 +220,7 @@ void pixel_minimap::set_settings( const pixel_minimap_settings &settings ) void pixel_minimap::prepare_cache_for_updates( const tripoint ¢er ) { - const tripoint new_center_sm = g->m.get_abs_sub() + ms_to_sm_copy( center ); + const tripoint new_center_sm = get_map().get_abs_sub() + ms_to_sm_copy( center ); const tripoint center_sm_diff = cached_center_sm - new_center_sm; //invalidate the cache if the game shifted more than one submap in the last update, or if z-level changed. @@ -295,10 +294,11 @@ void pixel_minimap::flush_cache_updates() void pixel_minimap::update_cache_at( const tripoint &sm_pos ) { - const level_cache &access_cache = g->m.access_cache( sm_pos.z ); - const bool nv_goggle = g->u.get_vision_modes()[NV_GOGGLES]; + const map &here = get_map(); + const level_cache &access_cache = here.access_cache( sm_pos.z ); + const bool nv_goggle = get_avatar().get_vision_modes()[NV_GOGGLES]; - submap_cache &cache_item = get_cache_at( g->m.get_abs_sub() + sm_pos ); + submap_cache &cache_item = get_cache_at( here.get_abs_sub() + sm_pos ); const tripoint ms_pos = sm_to_ms_copy( sm_pos ); cache_item.touched = true; @@ -445,7 +445,7 @@ void pixel_minimap::render( const tripoint ¢er ) void pixel_minimap::render_cache( const tripoint ¢er ) { - const tripoint sm_center = g->m.get_abs_sub() + ms_to_sm_copy( center ); + const tripoint sm_center = get_map().get_abs_sub() + ms_to_sm_copy( center ); const tripoint sm_offset = tripoint{ total_tiles_count.x / SEEX / 2, total_tiles_count.y / SEEY / 2, 0 @@ -494,7 +494,7 @@ void pixel_minimap::render_critters( const tripoint ¢er ) mixture = lerp_clamped( 0, 100, std::max( s, 0.0f ) ); } - const level_cache &access_cache = g->m.access_cache( center.z ); + const level_cache &access_cache = get_map().access_cache( center.z ); const int start_x = center.x - total_tiles_count.x / 2; const int start_y = center.y - total_tiles_count.y / 2; @@ -514,7 +514,7 @@ void pixel_minimap::render_critters( const tripoint ¢er ) const auto critter = g->critter_at( p, true ); - if( critter == nullptr || !g->u.sees( *critter ) ) { + if( critter == nullptr || !get_avatar().sees( *critter ) ) { continue; } diff --git a/src/sounds.cpp b/src/sounds.cpp index 9698f5c29e81e..0d48fc898703e 100644 --- a/src/sounds.cpp +++ b/src/sounds.cpp @@ -278,7 +278,7 @@ static int get_signal_for_hordes( const centroid ¢r ) { //Volume in tiles. Signal for hordes in submaps //modify vol using weather vol.Weather can reduce monster hearing - const int vol = centr.volume - weather::sound_attn( g->weather.weather ); + const int vol = centr.volume - weather::sound_attn( get_weather().weather ); const int min_vol_cap = 60; //Hordes can't hear volume lower than this const int underground_div = 2; //Coefficient for volume reduction underground const int hordes_sig_div = SEEX; //Divider coefficient for hordes @@ -302,7 +302,7 @@ static int get_signal_for_hordes( const centroid ¢r ) void sounds::process_sounds() { std::vector sound_clusters = cluster_sounds( recent_sounds ); - const int weather_vol = weather::sound_attn( g->weather.weather ); + const int weather_vol = weather::sound_attn( get_weather().weather ); for( const auto &this_centroid : sound_clusters ) { // Since monsters don't go deaf ATM we can just use the weather modified volume // If they later get physical effects from loud noises we'll have to change this @@ -314,7 +314,7 @@ void sounds::process_sounds() int sig_power = get_signal_for_hordes( this_centroid ); if( sig_power > 0 ) { - const point abs_ms = g->m.getabs( source.xy() ); + const point abs_ms = get_map().getabs( source.xy() ); const point abs_sm = ms_to_sm_copy( abs_ms ); const tripoint target( abs_sm, source.z ); overmap_buffer.signal_hordes( target, sig_power ); @@ -384,7 +384,7 @@ void sounds::process_sound_markers( player *p ) { bool is_deaf = p->is_deaf(); const float volume_multiplier = p->hearing_ability(); - const int weather_vol = weather::sound_attn( g->weather.weather ); + const int weather_vol = weather::sound_attn( get_weather().weather ); for( const auto &sound_event_pair : sounds_since_last_turn ) { const tripoint &pos = sound_event_pair.first; const sound_event &sound = sound_event_pair.second; @@ -464,7 +464,7 @@ void sounds::process_sound_markers( player *p ) } // don't print our own noise or things without descriptions - if( !sound.ambient && ( pos != p->pos() ) && !g->m.pl_sees( pos, distance_to_sound ) ) { + if( !sound.ambient && ( pos != p->pos() ) && !get_map().pl_sees( pos, distance_to_sound ) ) { if( !p->activity.is_distraction_ignored( distraction_type::noise ) && !get_safemode().is_sound_safe( sound.description, distance_to_sound ) ) { const std::string query = string_format( _( "Heard %s!" ), description ); @@ -536,7 +536,7 @@ void sounds::process_sound_markers( player *p ) // Enumerate the valid points the player *cannot* see. // Unless the source is on a different z-level, then any point is fine std::vector unseen_points; - for( const tripoint &newp : g->m.points_in_radius( pos, err_offset ) ) { + for( const tripoint &newp : get_map().points_in_radius( pos, err_offset ) ) { if( diff_z || !p->sees( newp ) ) { unseen_points.emplace_back( newp ); } @@ -647,19 +647,20 @@ int sfx::set_channel_volume( channel channel, int volume ) void sfx::do_vehicle_engine_sfx() { static const channel ch = channel::interior_engine_sound; - if( !g->u.in_vehicle ) { + const avatar &player_character = get_avatar(); + if( !player_character.in_vehicle ) { fade_audio_channel( ch, 300 ); add_msg( m_debug, "STOP interior_engine_sound, OUT OF CAR" ); return; } - if( g->u.in_sleep_state() && !audio_muted ) { + if( player_character.in_sleep_state() && !audio_muted ) { fade_audio_channel( channel::any, 300 ); audio_muted = true; return; - } else if( g->u.in_sleep_state() && audio_muted ) { + } else if( player_character.in_sleep_state() && audio_muted ) { return; } - optional_vpart_position vpart_opt = g->m.veh_at( g->u.pos() ); + optional_vpart_position vpart_opt = get_map().veh_at( player_character.pos() ); vehicle *veh; if( vpart_opt.has_value() ) { veh = &vpart_opt->vehicle(); @@ -694,7 +695,7 @@ void sfx::do_vehicle_engine_sfx() if( !is_channel_playing( ch ) ) { play_ambient_variant_sound( id_and_variant.first, id_and_variant.second, - sfx::get_heard_volume( g->u.pos() ), ch, 1000 ); + sfx::get_heard_volume( player_character.pos() ), ch, 1000 ); add_msg( m_debug, "START %s %s", id_and_variant.first, id_and_variant.second ); } else { add_msg( m_debug, "PLAYING" ); @@ -731,10 +732,12 @@ void sfx::do_vehicle_engine_sfx() } if( current_gear > previous_gear ) { - play_variant_sound( "vehicle", "gear_shift", get_heard_volume( g->u.pos() ), 0, 0.8, 0.8 ); + play_variant_sound( "vehicle", "gear_shift", get_heard_volume( player_character.pos() ), 0, 0.8, + 0.8 ); add_msg( m_debug, "GEAR UP" ); } else if( current_gear < previous_gear ) { - play_variant_sound( "vehicle", "gear_shift", get_heard_volume( g->u.pos() ), 0, 1.2, 1.2 ); + play_variant_sound( "vehicle", "gear_shift", get_heard_volume( player_character.pos() ), 0, 1.2, + 1.2 ); add_msg( m_debug, "GEAR DOWN" ); } if( ( safe_speed != 0 ) ) { @@ -754,7 +757,7 @@ void sfx::do_vehicle_engine_sfx() Mix_HaltChannel( static_cast( ch ) ); add_msg( m_debug, "STOP speed %d =/= %d", current_speed, previous_speed ); play_ambient_variant_sound( id_and_variant.first, id_and_variant.second, - sfx::get_heard_volume( g->u.pos() ), ch, 1000, pitch ); + sfx::get_heard_volume( player_character.pos() ), ch, 1000, pitch ); add_msg( m_debug, "PITCH %f", pitch ); } previous_speed = current_speed; @@ -765,21 +768,22 @@ void sfx::do_vehicle_exterior_engine_sfx() { static const channel ch = channel::exterior_engine_sound; static const int ch_int = static_cast( ch ); + const avatar &player_character = get_avatar(); // early bail-outs for efficiency - if( g->u.in_vehicle ) { + if( player_character.in_vehicle ) { fade_audio_channel( ch, 300 ); add_msg( m_debug, "STOP exterior_engine_sound, IN CAR" ); return; } - if( g->u.in_sleep_state() && !audio_muted ) { + if( player_character.in_sleep_state() && !audio_muted ) { fade_audio_channel( channel::any, 300 ); audio_muted = true; return; - } else if( g->u.in_sleep_state() && audio_muted ) { + } else if( player_character.in_sleep_state() && audio_muted ) { return; } - VehicleList vehs = g->m.get_vehicles(); + VehicleList vehs = get_map().get_vehicles(); unsigned char noise_factor = 0; unsigned char vol = 0; vehicle *veh = nullptr; @@ -787,9 +791,10 @@ void sfx::do_vehicle_exterior_engine_sfx() for( wrapped_vehicle vehicle : vehs ) { if( vehicle.v->vehicle_noise > 0 && vehicle.v->vehicle_noise - - sound_distance( g->u.pos(), vehicle.v->global_pos3() ) > noise_factor ) { + sound_distance( player_character.pos(), vehicle.v->global_pos3() ) > noise_factor ) { - noise_factor = vehicle.v->vehicle_noise - sound_distance( g->u.pos(), vehicle.v->global_pos3() ); + noise_factor = vehicle.v->vehicle_noise - sound_distance( player_character.pos(), + vehicle.v->global_pos3() ); veh = vehicle.v; } } @@ -850,19 +855,20 @@ void sfx::do_vehicle_exterior_engine_sfx() void sfx::do_ambient() { - if( g->u.in_sleep_state() && !audio_muted ) { + const avatar &player_character = get_avatar(); + if( player_character.in_sleep_state() && !audio_muted ) { fade_audio_channel( channel::any, 300 ); audio_muted = true; return; - } else if( g->u.in_sleep_state() && audio_muted ) { + } else if( player_character.in_sleep_state() && audio_muted ) { return; } audio_muted = false; - const bool is_deaf = g->u.is_deaf(); - const int heard_volume = get_heard_volume( g->u.pos() ); - const bool is_underground = g->u.pos().z < 0; - const bool is_sheltered = g->is_sheltered( g->u.pos() ); - const bool weather_changed = g->weather.weather != previous_weather; + const bool is_deaf = player_character.is_deaf(); + const int heard_volume = get_heard_volume( player_character.pos() ); + const bool is_underground = player_character.pos().z < 0; + const bool is_sheltered = g->is_sheltered( player_character.pos() ); + const bool weather_changed = get_weather().weather != previous_weather; // Step in at night time / we are not indoors if( is_night( calendar::turn ) && !is_sheltered && !is_channel_playing( channel::nighttime_outdoors_env ) && !is_deaf ) { @@ -893,14 +899,16 @@ void sfx::do_ambient() fade_audio_group( group::time_of_day, 1000 ); play_ambient_variant_sound( "environment", "indoors", heard_volume, channel::indoors_env, 1000 ); } + + weather_type current_weather = get_weather().weather; // We are indoors and it is also raining - if( g->weather.weather >= WEATHER_DRIZZLE && g->weather.weather <= WEATHER_ACID_RAIN && + if( current_weather >= WEATHER_DRIZZLE && current_weather <= WEATHER_ACID_RAIN && !is_underground && is_sheltered && !is_channel_playing( channel::indoors_rain_env ) ) { play_ambient_variant_sound( "environment", "indoors_rain", heard_volume, channel::indoors_rain_env, 1000 ); } - if( ( !is_sheltered && g->weather.weather != WEATHER_CLEAR && !is_deaf && + if( ( !is_sheltered && current_weather != WEATHER_CLEAR && !is_deaf && !is_channel_playing( channel::outdoors_snow_env ) && !is_channel_playing( channel::outdoors_flurry_env ) && !is_channel_playing( channel::outdoors_thunderstorm_env ) && @@ -911,7 +919,7 @@ void sfx::do_ambient() weather_changed && !is_deaf ) ) { fade_audio_group( group::weather, 1000 ); // We are outside and there is precipitation - switch( g->weather.weather ) { + switch( current_weather ) { case WEATHER_ACID_DRIZZLE: case WEATHER_DRIZZLE: case WEATHER_LIGHT_DRIZZLE: @@ -955,7 +963,7 @@ void sfx::do_ambient() } } // Keep track of weather to compare for next iteration - previous_weather = g->weather.weather; + previous_weather = current_weather; } // firing is the item that is fired. It may be the wielded gun, but it can also be an attached @@ -978,8 +986,9 @@ void sfx::generate_gun_sound( const player &source_arg, const item &firing ) int angle = 0; int distance = 0; std::string selected_sound; - // this does not mean p == g->u (it could be a vehicle turret) - if( g->u.pos() == source ) { + const avatar &player_character = get_avatar(); + // this does not mean p == avatar (it could be a vehicle turret) + if( player_character.pos() == source ) { selected_sound = "fire_gun"; const auto mods = firing.gunmods(); @@ -992,7 +1001,7 @@ void sfx::generate_gun_sound( const player &source_arg, const item &firing ) } else { angle = get_heard_angle( source ); - distance = sound_distance( g->u.pos(), source ); + distance = sound_distance( player_character.pos(), source ); if( distance <= 17 ) { selected_sound = "fire_gun"; } else { @@ -1175,19 +1184,20 @@ void sfx::do_player_death_hurt( const player &target, bool death ) void sfx::do_danger_music() { - if( g->u.in_sleep_state() && !audio_muted ) { + avatar &player_character = get_avatar(); + if( player_character.in_sleep_state() && !audio_muted ) { fade_audio_channel( channel::any, 100 ); audio_muted = true; return; - } else if( ( g->u.in_sleep_state() && audio_muted ) || + } else if( ( player_character.in_sleep_state() && audio_muted ) || is_channel_playing( channel::chainsaw_theme ) ) { fade_audio_group( group::context_themes, 1000 ); return; } audio_muted = false; int hostiles = 0; - for( auto &critter : g->u.get_visible_creatures( 40 ) ) { - if( g->u.attitude_to( *critter ) == Creature::Attitude::HOSTILE ) { + for( auto &critter : player_character.get_visible_creatures( 40 ) ) { + if( player_character.attitude_to( *critter ) == Creature::Attitude::HOSTILE ) { hostiles++; } } @@ -1225,43 +1235,46 @@ void sfx::do_danger_music() void sfx::do_fatigue() { + avatar &player_character = get_avatar(); /*15: Stamina 75% 16: Stamina 50% 17: Stamina 25%*/ - if( g->u.get_stamina() >= g->u.get_stamina_max() * .75 ) { + if( player_character.get_stamina() >= player_character.get_stamina_max() * .75 ) { fade_audio_group( group::fatigue, 2000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .74 - && g->u.get_stamina() >= g->u.get_stamina_max() * .5 && - g->u.male && !is_channel_playing( channel::stamina_75 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .74 && + player_character.get_stamina() >= player_character.get_stamina_max() * .5 && + player_character.male && !is_channel_playing( channel::stamina_75 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_m_low", 100, channel::stamina_75, 1000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .49 - && g->u.get_stamina() >= g->u.get_stamina_max() * .25 && - g->u.male && !is_channel_playing( channel::stamina_50 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .49 && + player_character.get_stamina() >= player_character.get_stamina_max() * .25 && + player_character.male && !is_channel_playing( channel::stamina_50 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_m_med", 100, channel::stamina_50, 1000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .24 && g->u.get_stamina() >= 0 && - g->u.male && !is_channel_playing( channel::stamina_35 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .24 && + player_character.get_stamina() >= 0 && player_character.male && + !is_channel_playing( channel::stamina_35 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_m_high", 100, channel::stamina_35, 1000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .74 - && g->u.get_stamina() >= g->u.get_stamina_max() * .5 && - !g->u.male && !is_channel_playing( channel::stamina_75 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .74 && + player_character.get_stamina() >= player_character.get_stamina_max() * .5 && + !player_character.male && !is_channel_playing( channel::stamina_75 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_f_low", 100, channel::stamina_75, 1000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .49 - && g->u.get_stamina() >= g->u.get_stamina_max() * .25 && - !g->u.male && !is_channel_playing( channel::stamina_50 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .49 && + player_character.get_stamina() >= player_character.get_stamina_max() * .25 && + !player_character.male && !is_channel_playing( channel::stamina_50 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_f_med", 100, channel::stamina_50, 1000 ); return; - } else if( g->u.get_stamina() <= g->u.get_stamina_max() * .24 && g->u.get_stamina() >= 0 && - !g->u.male && !is_channel_playing( channel::stamina_35 ) ) { + } else if( player_character.get_stamina() <= player_character.get_stamina_max() * .24 && + player_character.get_stamina() >= 0 && !player_character.male && + !is_channel_playing( channel::stamina_35 ) ) { fade_audio_group( group::fatigue, 1000 ); play_ambient_variant_sound( "plmove", "fatigue_f_high", 100, channel::stamina_35, 1000 ); return; @@ -1302,8 +1315,9 @@ void sfx::do_footstep() end_sfx_timestamp = std::chrono::high_resolution_clock::now(); sfx_time = end_sfx_timestamp - start_sfx_timestamp; if( std::chrono::duration_cast ( sfx_time ).count() > 400 ) { - int heard_volume = sfx::get_heard_volume( g->u.pos() ); - const auto terrain = g->m.ter( g->u.pos() ).id(); + const avatar &player_character = get_avatar(); + int heard_volume = sfx::get_heard_volume( player_character.pos() ); + const auto terrain = get_map().ter( player_character.pos() ).id(); static const std::set grass = { ter_str_id( "t_grass" ), ter_str_id( "t_shrub" ), @@ -1394,7 +1408,7 @@ void sfx::do_footstep() static const std::set chain_fence = { ter_str_id( "t_chainfence" ), }; - if( !g->u.wearing_something_on( bodypart_id( "foot_l" ) ) ) { + if( !player_character.wearing_something_on( bodypart_id( "foot_l" ) ) ) { play_variant_sound( "plmove", "walk_barefoot", heard_volume, 0, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); return; @@ -1432,7 +1446,7 @@ void sfx::do_footstep() void sfx::do_obstacle( const std::string &obst ) { - int heard_volume = sfx::get_heard_volume( g->u.pos() ); + int heard_volume = sfx::get_heard_volume( get_avatar().pos() ); if( sfx::has_variant_sound( "plmove", obst ) ) { play_variant_sound( "plmove", obst, heard_volume, 0, 0.8, 1.2 ); } else if( ter_str_id( obst ).is_valid() && @@ -1446,8 +1460,9 @@ void sfx::do_obstacle( const std::string &obst ) void sfx::play_activity_sound( const std::string &id, const std::string &variant, int volume ) { - if( act != g->u.activity.id() ) { - act = g->u.activity.id(); + avatar &player_character = get_avatar(); + if( act != player_character.activity.id() ) { + act = player_character.activity.id(); play_ambient_variant_sound( id, variant, volume, channel::player_activities, 0 ); } } @@ -1510,7 +1525,7 @@ void sfx::do_obstacle( const std::string & ) { } /*@{*/ int sfx::get_heard_volume( const tripoint &source ) { - int distance = sound_distance( g->u.pos(), source ); + int distance = sound_distance( get_avatar().pos(), source ); // fract = -100 / 24 const float fract = -4.166666; int heard_volume = fract * distance - 1 + 100; @@ -1523,7 +1538,7 @@ int sfx::get_heard_volume( const tripoint &source ) int sfx::get_heard_angle( const tripoint &source ) { - int angle = coord_to_angle( g->u.pos(), source ) + 90; + int angle = coord_to_angle( get_avatar().pos(), source ) + 90; //add_msg(m_warning, "angle: %i", angle); return ( angle ); } diff --git a/src/visitable.cpp b/src/visitable.cpp index a1808eab944d3..60c4be63ec7b8 100644 --- a/src/visitable.cpp +++ b/src/visitable.cpp @@ -14,7 +14,6 @@ #include "character.h" #include "colony.h" #include "debug.h" -#include "game.h" #include "inventory.h" #include "item.h" #include "item_contents.h" @@ -469,13 +468,13 @@ VisitResponse visitable::visit_items( const std::function &func ) { auto cur = static_cast( this ); - + map &here = get_map(); // skip inaccessible items - if( g->m.has_flag( "SEALED", *cur ) && !g->m.has_flag( "LIQUIDCONT", *cur ) ) { + if( here.has_flag( "SEALED", *cur ) && !here.has_flag( "LIQUIDCONT", *cur ) ) { return VisitResponse::NEXT; } - for( item &e : g->m.i_at( *cur ) ) { + for( item &e : here.i_at( *cur ) ) { if( visit_internal( func, &e ) == VisitResponse::ABORT ) { return VisitResponse::ABORT; } @@ -671,14 +670,15 @@ std::list visitable::remove_items_with( const return res; } - if( !g->m.inbounds( *cur ) ) { + map &here = get_map(); + if( !here.inbounds( *cur ) ) { debugmsg( "cannot remove items from map: cursor out-of-bounds" ); return res; } // fetch the appropriate item stack point offset; - submap *sub = g->m.get_submap_at( *cur, offset ); + submap *sub = here.get_submap_at( *cur, offset ); cata::colony &stack = sub->get_items( offset ); for( auto iter = stack.begin(); iter != stack.end(); ) { @@ -704,7 +704,7 @@ std::list visitable::remove_items_with( const ++iter; } } - g->m.update_submap_active_item_status( *cur ); + here.update_submap_active_item_status( *cur ); return res; } diff --git a/tests/archery_damage_test.cpp b/tests/archery_damage_test.cpp index 5be08c27c436d..fd607750040d2 100644 --- a/tests/archery_damage_test.cpp +++ b/tests/archery_damage_test.cpp @@ -17,7 +17,6 @@ #include "catch/catch.hpp" #include "damage.h" -#include "game.h" #include "game_constants.h" #include "int_id.h" #include "item.h" @@ -34,19 +33,20 @@ static void test_projectile_hitting_wall( const std::string &target_type, bool s dealt_projectile_attack &attack, const std::string &weapon_type ) { static const tripoint target_point{ 5, 5, 0 }; + map &here = get_map(); for( int i = 0; i < 10; ++i ) { projectile projectile_copy = attack.proj; - g->m.set( target_point, ter_id( target_type ), furn_id( "f_null" ) ); + here.set( target_point, ter_id( target_type ), furn_id( "f_null" ) ); CAPTURE( projectile_copy.impact.total_damage() ); - g->m.shoot( target_point, projectile_copy, false ); + here.shoot( target_point, projectile_copy, false ); CAPTURE( target_type ); CAPTURE( weapon_type ); CAPTURE( ter_id( target_type ).obj().name() ); - CAPTURE( g->m.ter( target_point ).obj().name() ); + CAPTURE( here.ter( target_point ).obj().name() ); if( smashable ) { - CHECK( g->m.ter( target_point ) != ter_id( target_type ) ); + CHECK( here.ter( target_point ) != ter_id( target_type ) ); } else { - CHECK( g->m.ter( target_point ) == ter_id( target_type ) ); + CHECK( here.ter( target_point ) == ter_id( target_type ) ); } } } diff --git a/tests/modify_morale_test.cpp b/tests/modify_morale_test.cpp index c1188a84048d3..b05bf6b887fdc 100644 --- a/tests/modify_morale_test.cpp +++ b/tests/modify_morale_test.cpp @@ -6,7 +6,6 @@ #include "avatar.h" #include "catch/catch.hpp" -#include "game.h" #include "item.h" #include "map.h" #include "map_helpers.h" @@ -79,6 +78,7 @@ TEST_CASE( "food enjoyability", "[food][modify_morale][fun]" ) TEST_CASE( "dining with table and chair", "[food][modify_morale][table][chair]" ) { clear_map(); + map &here = get_map(); avatar dummy; const tripoint avatar_pos( 60, 60, 0 ); dummy.setpos( avatar_pos ); @@ -109,8 +109,8 @@ TEST_CASE( "dining with table and chair", "[food][modify_morale][table][chair]" }; GIVEN( "no table or chair are nearby" ) { - REQUIRE_FALSE( g->m.has_nearby_table( dummy.pos(), 1 ) ); - REQUIRE_FALSE( g->m.has_nearby_chair( dummy.pos(), 1 ) ); + REQUIRE_FALSE( here.has_nearby_table( dummy.pos(), 1 ) ); + REQUIRE_FALSE( here.has_nearby_chair( dummy.pos(), 1 ) ); AND_GIVEN( "character has normal table manners" ) { REQUIRE_FALSE( dummy.has_trait( trait_TABLEMANNERS ) ); @@ -145,10 +145,10 @@ TEST_CASE( "dining with table and chair", "[food][modify_morale][table][chair]" } GIVEN( "a table and chair are nearby" ) { - g->m.furn_set( avatar_pos + tripoint_north, furn_id( "f_table" ) ); - g->m.furn_set( avatar_pos + tripoint_east, furn_id( "f_chair" ) ); - REQUIRE( g->m.has_nearby_table( dummy.pos(), 1 ) ); - REQUIRE( g->m.has_nearby_chair( dummy.pos(), 1 ) ); + here.furn_set( avatar_pos + tripoint_north, furn_id( "f_table" ) ); + here.furn_set( avatar_pos + tripoint_east, furn_id( "f_chair" ) ); + REQUIRE( here.has_nearby_table( dummy.pos(), 1 ) ); + REQUIRE( here.has_nearby_chair( dummy.pos(), 1 ) ); AND_GIVEN( "character has normal table manners" ) { REQUIRE_FALSE( dummy.has_trait( trait_TABLEMANNERS ) ); diff --git a/tests/projectile_test.cpp b/tests/projectile_test.cpp index 8ba6c87fcb0ef..c1bfb3aff4303 100644 --- a/tests/projectile_test.cpp +++ b/tests/projectile_test.cpp @@ -21,7 +21,8 @@ static tripoint projectile_end_point( const std::vector &range, const dealt_projectile_attack attack; - attack = projectile_attack( test_proj, range[0], range[2], dispersion_sources(), &g->u, nullptr ); + attack = projectile_attack( test_proj, range[0], range[2], dispersion_sources(), &get_avatar(), + nullptr ); return attack.end_point; } @@ -29,24 +30,25 @@ static tripoint projectile_end_point( const std::vector &range, const TEST_CASE( "projectiles_through_obstacles", "[projectile]" ) { clear_map(); + map &here = get_map(); // Move the player out of the way of the test area - g->u.setpos( { 2, 2, 0 } ); + get_avatar().setpos( { 2, 2, 0 } ); // Ensure that a projectile fired from a gun can pass through a chain link fence // First, set up a test area - three tiles in a row // One on either side clear, with a chainlink fence in the middle std::vector range = { tripoint_zero, tripoint_east, tripoint( 2, 0, 0 ) }; for( const tripoint &pt : range ) { - REQUIRE( g->m.inbounds( pt ) ); - g->m.ter_set( pt, ter_id( "t_dirt" ) ); - g->m.furn_set( pt, furn_id( "f_null" ) ); + REQUIRE( here.inbounds( pt ) ); + here.ter_set( pt, ter_id( "t_dirt" ) ); + here.furn_set( pt, furn_id( "f_null" ) ); REQUIRE_FALSE( g->critter_at( pt ) ); - REQUIRE( g->m.is_transparent( pt ) ); + REQUIRE( here.is_transparent( pt ) ); } // Set an obstacle in the way, a chain fence - g->m.ter_set( range[1], ter_id( "t_chainfence" ) ); + here.ter_set( range[1], ter_id( "t_chainfence" ) ); // Create a gun to fire a projectile from item gun( itype_id( "m1a" ) ); diff --git a/tests/vehicle_power_test.cpp b/tests/vehicle_power_test.cpp index c51da30ba6bd8..74b0fbb5fb372 100644 --- a/tests/vehicle_power_test.cpp +++ b/tests/vehicle_power_test.cpp @@ -6,7 +6,6 @@ #include "bodypart.h" #include "calendar.h" #include "catch/catch.hpp" -#include "game.h" #include "map.h" #include "map_helpers.h" #include "point.h" @@ -20,11 +19,12 @@ static const efftype_id effect_blind( "blind" ); static void reset_player() { + avatar &player_character = get_avatar(); // Move player somewhere safe - REQUIRE( !g->u.in_vehicle ); - g->u.setpos( tripoint_zero ); + REQUIRE( !player_character.in_vehicle ); + player_character.setpos( tripoint_zero ); // Blind the player to avoid needless drawing-related overhead - g->u.add_effect( effect_blind, 1_turns, num_bp, true ); + player_character.add_effect( effect_blind, 1_turns, num_bp, true ); } TEST_CASE( "vehicle power with reactor and solar panels", "[vehicle][power]" ) @@ -32,10 +32,11 @@ TEST_CASE( "vehicle power with reactor and solar panels", "[vehicle][power]" ) reset_player(); build_test_map( ter_id( "t_pavement" ) ); clear_vehicles(); + map &here = get_map(); SECTION( "vehicle with reactor" ) { const tripoint reactor_origin = tripoint( 10, 10, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "reactor_test" ), reactor_origin, 0, 0, 0 ); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "reactor_test" ), reactor_origin, 0, 0, 0 ); REQUIRE( veh_ptr != nullptr ); REQUIRE( !veh_ptr->reactors.empty() ); @@ -63,14 +64,14 @@ TEST_CASE( "vehicle power with reactor and solar panels", "[vehicle][power]" ) SECTION( "vehicle with solar panels" ) { const tripoint solar_origin = tripoint( 5, 5, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "solar_panel_test" ), solar_origin, 0, 0, 0 ); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "solar_panel_test" ), solar_origin, 0, 0, 0 ); REQUIRE( veh_ptr != nullptr ); GIVEN( "it is 3 hours after sunrise, with sunny weather" ) { calendar::turn = calendar::turn_zero + calendar::season_length() + 1_days; const time_point start_time = sunrise( calendar::turn ) + 3_hours; veh_ptr->update_time( start_time ); - g->weather.weather_override = WEATHER_SUNNY; + get_weather().weather_override = WEATHER_SUNNY; AND_GIVEN( "the battery has no charge" ) { veh_ptr->discharge_battery( veh_ptr->fuel_left( fuel_type_battery ) ); @@ -100,7 +101,7 @@ TEST_CASE( "vehicle power with reactor and solar panels", "[vehicle][power]" ) GIVEN( "it is 3 hours after sunset, with clear weather" ) { const time_point at_night = sunset( calendar::turn ) + 3_hours; - g->weather.weather_override = WEATHER_CLEAR; + get_weather().weather_override = WEATHER_CLEAR; veh_ptr->update_time( at_night ); AND_GIVEN( "the battery has no charge" ) { @@ -124,10 +125,11 @@ TEST_CASE( "maximum reverse velocity", "[vehicle][power][reverse]" ) reset_player(); build_test_map( ter_id( "t_pavement" ) ); clear_vehicles(); + map &here = get_map(); GIVEN( "a scooter with combustion engine and charged battery" ) { const tripoint origin = tripoint( 10, 0, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "scooter_test" ), origin, 0, 0, 0 ); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "scooter_test" ), origin, 0, 0, 0 ); REQUIRE( veh_ptr != nullptr ); veh_ptr->charge_battery( 500 ); REQUIRE( veh_ptr->fuel_left( fuel_type_battery ) == 500 ); @@ -152,7 +154,7 @@ TEST_CASE( "maximum reverse velocity", "[vehicle][power][reverse]" ) GIVEN( "a scooter with an electric motor and charged battery" ) { const tripoint origin = tripoint( 15, 0, 0 ); - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "scooter_electric_test" ), origin, 0, 0, 0 ); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "scooter_electric_test" ), origin, 0, 0, 0 ); REQUIRE( veh_ptr != nullptr ); veh_ptr->charge_battery( 5000 ); REQUIRE( veh_ptr->fuel_left( fuel_type_battery ) == 5000 ); diff --git a/tests/vehicle_test.cpp b/tests/vehicle_test.cpp index b2e255bb83729..82cbe00928294 100644 --- a/tests/vehicle_test.cpp +++ b/tests/vehicle_test.cpp @@ -5,7 +5,6 @@ #include "catch/catch.hpp" #include "damage.h" #include "enums.h" -#include "game.h" #include "item.h" #include "map.h" #include "map_helpers.h" @@ -19,31 +18,35 @@ TEST_CASE( "detaching_vehicle_unboards_passengers" ) clear_map(); const tripoint test_origin( 60, 60, 0 ); const tripoint vehicle_origin = test_origin; - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90, 0, 0 ); - g->m.board_vehicle( test_origin, &g->u ); - REQUIRE( g->u.in_vehicle ); - g->m.detach_vehicle( veh_ptr ); - REQUIRE( !g->u.in_vehicle ); + map &here = get_map(); + avatar &player_character = get_avatar(); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90, 0, 0 ); + here.board_vehicle( test_origin, &player_character ); + REQUIRE( player_character.in_vehicle ); + here.detach_vehicle( veh_ptr ); + REQUIRE( !player_character.in_vehicle ); } TEST_CASE( "destroy_grabbed_vehicle_section" ) { GIVEN( "A vehicle grabbed by the player" ) { + map &here = get_map(); const tripoint test_origin( 60, 60, 0 ); - g->place_player( test_origin ); + avatar &player_character = get_avatar(); + player_character.setpos( test_origin ); const tripoint vehicle_origin = test_origin + tripoint_south_east; - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90, 0, 0 ); + vehicle *veh_ptr = here.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90, 0, 0 ); REQUIRE( veh_ptr != nullptr ); tripoint grab_point = test_origin + tripoint_east; - g->u.grab( object_type::VEHICLE, grab_point ); - REQUIRE( g->u.get_grab_type() != object_type::NONE ); - REQUIRE( g->u.grab_point == grab_point ); + player_character.grab( object_type::VEHICLE, grab_point ); + REQUIRE( player_character.get_grab_type() != object_type::NONE ); + REQUIRE( player_character.grab_point == grab_point ); WHEN( "The vehicle section grabbed by the player is destroyed" ) { - g->m.destroy( grab_point ); + here.destroy( grab_point ); REQUIRE( veh_ptr->get_parts_at( grab_point, "", part_status_flag::available ).empty() ); THEN( "The player's grab is released" ) { - CHECK( g->u.get_grab_type() == object_type::NONE ); - CHECK( g->u.grab_point == tripoint_zero ); + CHECK( player_character.get_grab_type() == object_type::NONE ); + CHECK( player_character.grab_point == tripoint_zero ); } } } @@ -54,7 +57,7 @@ TEST_CASE( "add_item_to_broken_vehicle_part" ) clear_map(); const tripoint test_origin( 60, 60, 0 ); const tripoint vehicle_origin = test_origin; - vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, 0, 0, 0 ); + vehicle *veh_ptr = get_map().add_vehicle( vproto_id( "bicycle" ), vehicle_origin, 0, 0, 0 ); REQUIRE( veh_ptr != nullptr ); const tripoint pos = vehicle_origin + tripoint_west; From 618677d66539c9b68bab3a16bdafc963fe375201 Mon Sep 17 00:00:00 2001 From: Kevin Granade Date: Sun, 28 Jun 2020 19:20:17 -0700 Subject: [PATCH 16/41] Tweak hunger test numbers after fillingness adjustment. (#41666) --- tests/stomach_contents_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/stomach_contents_test.cpp b/tests/stomach_contents_test.cpp index 33c80899df04a..6f5a81094a27c 100644 --- a/tests/stomach_contents_test.cpp +++ b/tests/stomach_contents_test.cpp @@ -268,8 +268,8 @@ TEST_CASE( "hunger" ) if( print_tests ) { printf( "%d minutes til hunger sets in\n", hunger_time ); } - CHECK( hunger_time <= 435 ); - CHECK( hunger_time >= 405 ); + CHECK( hunger_time <= 375 ); + CHECK( hunger_time >= 345 ); if( print_tests ) { print_stomach_contents( dummy, print_tests ); printf( "eat 16 veggy\n" ); From 414149f44791fe5ddab2d69df63d1e422afe5dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jianxiang=20Wang=20=28=E7=8E=8B=E5=81=A5=E7=BF=94=29?= Date: Mon, 29 Jun 2020 14:09:52 +0800 Subject: [PATCH 17/41] Dialogue text style (#41629) * Use class translation in dynamic_line_t * Fix json text style --- data/json/achievements.json | 2 +- data/json/npcs/Backgrounds/cop_2.json | 2 +- data/json/npcs/Backgrounds/prisoner_1.json | 2 +- data/json/npcs/NPC_Brigitte_LaCroix.json | 34 +++++++++---------- data/json/npcs/TALK_ALLY_TUTORIAL.json | 2 +- data/json/npcs/TALK_CITY_COP.json | 4 +-- data/json/npcs/TALK_COMMON_ALLY.json | 6 ++-- data/json/npcs/TALK_COMMON_GREET.json | 2 +- data/json/npcs/TALK_COMMON_OTHER.json | 8 ++--- data/json/npcs/TALK_CYBORG_1.json | 12 +++---- data/json/npcs/TALK_FRIEND_CONVERSATION.json | 2 +- data/json/npcs/TALK_MARLOSS_VOICE.json | 2 +- data/json/npcs/TALK_NC_FARMER.json | 2 +- data/json/npcs/TALK_TRUE_FOODPERSON.json | 2 +- .../isherwood_farm/NPC_Carlos_Isherwood.json | 2 +- .../isherwood_farm/NPC_Chris_Isherwood.json | 2 +- .../isherwood_farm/NPC_Eddie_Isherwood.json | 2 +- .../isherwood_farm/NPC_Jack_Isherwood.json | 2 +- .../isherwood_farm/NPC_Jesse_Isherwood.json | 2 +- .../isherwood_farm/NPC_Lisa_Isherwood.json | 2 +- .../isherwood_farm/NPC_Luke_Isherwood.json | 2 +- data/json/npcs/missiondef.json | 4 +-- .../beggars/BEGGAR_5_Yusuke_Taylor.json | 2 +- .../surface_refugees/NPC_Draco_Dune.json | 2 +- .../surface_refugees/NPC_Pablo_Nunez.json | 2 +- .../surface_refugees/NPC_Rhyzaea_Johnny.json | 2 +- .../surface_refugees/NPC_Stan_Borichenko.json | 2 +- .../NPC_free_merchant_broker.json | 4 +-- .../NPC_free_merchant_guard_generic.json | 2 +- .../NPC_free_merchant_shopkeep.json | 2 +- .../surface_staff/NPC_old_guard_doctor.json | 2 +- .../NPC_old_guard_representative.json | 2 +- .../npcs/robofac/NPC_ROBOFAC_INTERCOM.json | 2 +- .../json/npcs/robofac/NPC_ROBOFAC_MERC_1.json | 6 ++-- .../robofac/ROBOFAC_SURFACE_FREEMERCHANT.json | 4 +-- .../npcs/tacoma_ranch/NPC_ranch_barber.json | 2 +- .../npcs/tacoma_ranch/NPC_ranch_guard.json | 2 +- .../NPC_ranch_sickly_laborer.json | 6 ++-- .../Aftershock/npcs/prepnet_dialogue.json | 2 +- data/mods/DinoMod/NPC/NC_BO_BARONYX.json | 4 +-- data/mods/Magiclysm/npc/TALK_OLD_MAGUS.json | 4 +-- src/dialogue.h | 2 +- src/npctalk.cpp | 22 +++++++++--- 43 files changed, 95 insertions(+), 83 deletions(-) diff --git a/data/json/achievements.json b/data/json/achievements.json index 551a136df06a3..bbe0bf7f184c1 100644 --- a/data/json/achievements.json +++ b/data/json/achievements.json @@ -73,7 +73,7 @@ "id": "achievement_marathon", "type": "achievement", "name": "Pheidippides was a hack", - "description": "Run a marathon…plus a little bit more.", + "description": "Run a marathon… plus a little bit more.", "requirements": [ { "event_statistic": "num_moves_ran", "is": ">=", "target": 42196 } ] }, { diff --git a/data/json/npcs/Backgrounds/cop_2.json b/data/json/npcs/Backgrounds/cop_2.json index 77ea7453edfcf..6d0a9ff34786c 100644 --- a/data/json/npcs/Backgrounds/cop_2.json +++ b/data/json/npcs/Backgrounds/cop_2.json @@ -11,7 +11,7 @@ { "id": "BGSS_COP_2_STORY2", "type": "talk_topic", - "dynamic_line": "Eventually yes. It had been quiet for hours. I was parched, injured, and terrified. My training was maybe the only thing that kept me from freaking out. I decided to try to pull myself out and see how bad my injuries were. It was easy. The side of the van was torn open, and it turned out I was basically just lying under a little debris, with the ruins of the van tented around me. I wasn't even too badly hurt. I grabbed as much gear as I could, and I slipped out. It was night. I could hear fighting farther away in the city, so I went the other way. I made it a few blocks before I ran into any ... I ran from them. I ran, and I ran, and I ran some more. And here I am.", + "dynamic_line": "Eventually yes. It had been quiet for hours. I was parched, injured, and terrified. My training was maybe the only thing that kept me from freaking out. I decided to try to pull myself out and see how bad my injuries were. It was easy. The side of the van was torn open, and it turned out I was basically just lying under a little debris, with the ruins of the van tented around me. I wasn't even too badly hurt. I grabbed as much gear as I could, and I slipped out. It was night. I could hear fighting farther away in the city, so I went the other way. I made it a few blocks before I ran into any … I ran from them. I ran, and I ran, and I ran some more. And here I am.", "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/prisoner_1.json b/data/json/npcs/Backgrounds/prisoner_1.json index 70c9ee5bf9c42..61e5c15bea938 100644 --- a/data/json/npcs/Backgrounds/prisoner_1.json +++ b/data/json/npcs/Backgrounds/prisoner_1.json @@ -190,7 +190,7 @@ { "id": "BGSS_PRISONER_1_IN_FOR_TAXEVASION", "type": "talk_topic", - "dynamic_line": "Tax evasion. I was an accountant, and I helped my boss move a hell of a lot of money in some very clever ways. Not clever enough, it turns out...", + "dynamic_line": "Tax evasion. I was an accountant, and I helped my boss move a hell of a lot of money in some very clever ways. Not clever enough, it turns out…", "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] }, { diff --git a/data/json/npcs/NPC_Brigitte_LaCroix.json b/data/json/npcs/NPC_Brigitte_LaCroix.json index 8d3eecaf658d2..04b243421e9e9 100644 --- a/data/json/npcs/NPC_Brigitte_LaCroix.json +++ b/data/json/npcs/NPC_Brigitte_LaCroix.json @@ -101,13 +101,13 @@ "type": "dialogue", "context": "first_meeting", "value": "yes", - "no": "You there. Quiet down. Can you hear it? The song?", + "no": "You there. Quiet down. Can you hear it? The song?", "yes": { "u_has_var": "asked_about_song", "type": "dialogue", "context": "song", "value": "yes", - "no": "You're back. Have you come to listen to the song?", + "no": "You're back. Have you come to listen to the song?", "yes": "Acolyte." } }, @@ -146,7 +146,7 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_SONG", - "dynamic_line": "Listen carefully. The bones… they sing. Can you hear it? The song they weave? The stories they hold?", + "dynamic_line": "Listen carefully. The bones… they sing. Can you hear it? The song they weave? The stories they hold?", "responses": [ { "text": "What? Singing bones? What are you talking about?", "topic": "TALK_BONE_SEER_SONG2" }, { "text": "Uh… yeah, sure. I think I'll just be on my way.", "topic": "TALK_DONE" } @@ -155,7 +155,7 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_SONG2", - "dynamic_line": "When it all happened, the Cataclysm, something… changed. You can see it in all creatures, but most of all their bones. They break, morph, rise again, in an infinite cycle. Living dead walk. Monsters rip and tear each other apart. You can see the resonance, the quiet hum of raw strength, and only by taking the bones does the cycle end - their story, their song, their strength, become yours to use.", + "dynamic_line": "When it all happened, the Cataclysm, something… changed. You can see it in all creatures, but most of all their bones. They break, morph, rise again, in an infinite cycle. Living dead walk. Monsters rip and tear each other apart. You can see the resonance, the quiet hum of raw strength, and only by taking the bones does the cycle end - their story, their song, their strength, become yours to use.", "responses": [ { "text": "So what do you actually do with the bones?", "topic": "TALK_BONE_SEER_BONES" }, { "text": "I'm still not quite sure what you mean about songs or strength.", "topic": "TALK_BONE_SEER_SONG3" }, @@ -165,13 +165,13 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_SONG3", - "dynamic_line": "Only when you crush the bones of a body does it cease to rise. Only if you examine the bones can you see what was. Thus is the story. Whatever causes this change is alive, moving within us all, an inevitable part of this new world. It holds the power of change. When we hold the bones, we hold the power. Thus the strength. Together… they form a beautiful song.", + "dynamic_line": "Only when you crush the bones of a body does it cease to rise. Only if you examine the bones can you see what was. Thus is the story. Whatever causes this change is alive, moving within us all, an inevitable part of this new world. It holds the power of change. When we hold the bones, we hold the power. Thus the strength. Together… they form a beautiful song.", "responses": [ { "text": "I think I understand what you mean, though I am not sure if I agree.", "topic": "TALK_NONE" } ] }, { "type": "talk_topic", "id": "TALK_BONE_SEER_OTHERS", - "dynamic_line": "There are others who follow this cause. You'd do well to aid them, for though we may not be numerous, we are emboldened by the songs we carry.", + "dynamic_line": "There are others who follow this cause. You'd do well to aid them, for though we may not be numerous, we are emboldened by the songs we carry.", "responses": [ { "text": "I will bear that in mind.", "topic": "TALK_NONE" }, { "text": "Cause? Why do you gather these bones anyway?", "topic": "TALK_BONE_SEER_BONES" } @@ -180,13 +180,13 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_BONES", - "dynamic_line": "The song can be weaved in many forms. Carved bone charms, weapons and armor all hold immense power, and when the time comes, me and my kindred shall gather a great amount of song and sing it to restore this world. Restore it, or end it. Makes no difference.", + "dynamic_line": "The song can be weaved in many forms. Carved bone charms, weapons and armor all hold immense power, and when the time comes, me and my kindred shall gather a great amount of song and sing it to restore this world. Restore it, or end it. Makes no difference.", "responses": [ { "text": "End the world? What?", "topic": "TALK_BONE_SEER_END" } ] }, { "type": "talk_topic", "id": "TALK_BONE_SEER_END", - "dynamic_line": "We believe that enough power in one song could revert the Cataclysm - or accelerate it to a time beyond all, ending it all the same. But with the world looking as is, both options are preferable.", + "dynamic_line": "We believe that enough power in one song could revert the Cataclysm - or accelerate it to a time beyond all, ending it all the same. But with the world looking as is, both options are preferable.", "responses": [ { "text": "Sounds somewhat… doomsday-ish, but I suppose it's a belief like any other. Still, at least you have a goal to help the world, one way or another.", @@ -198,13 +198,13 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_ACOLYTE", - "dynamic_line": "Your mind is open. More than most. Perhaps one day, you too will feel the power of the song and become Kindred. For now, Acolyte, listen, listen and feel the song.", + "dynamic_line": "Your mind is open. More than most. Perhaps one day, you too will feel the power of the song and become Kindred. For now, Acolyte, listen, listen and feel the song.", "responses": [ { "text": "I… thank you.", "topic": "TALK_BONE_SEER" } ] }, { "type": "talk_topic", "id": "TALK_BONE_SEER_INSULT", - "dynamic_line": "Your skepticism does not surprise me. Perhaps one day, you too will hear the inevitability of the song, feel its power. But until then, you will remain an Acolyte, path to the Kindred closed.", + "dynamic_line": "Your skepticism does not surprise me. Perhaps one day, you too will hear the inevitability of the song, feel its power. But until then, you will remain an Acolyte, path to the Kindred closed.", "responses": [ { "text": "Yeah, alright.", "topic": "TALK_BONE_SEER" } ] }, { @@ -277,7 +277,7 @@ { "id": "TALK_MISSION_OFFER_SEER", "type": "talk_topic", - "dynamic_line": "If you wish to be set on the path to enlightenment, first you must learn to listen and hear the song. Go out, butcher a creature and feel the power between your fingertips. Then bring me the bones and I shall carve them for you. ", + "dynamic_line": "If you wish to be set on the path to enlightenment, first you must learn to listen and hear the song. Go out, butcher a creature and feel the power between your fingertips. Then bring me the bones and I shall carve them for you.", "responses": [ { "text": "Well, I guess I oughta see where this goes. I'm in.", @@ -290,7 +290,7 @@ { "id": "TALK_MISSION_ACCEPTED_SEER", "type": "talk_topic", - "dynamic_line": "Excellent. Now be on your way.", + "dynamic_line": "Excellent. Now be on your way.", "responses": [ { "text": "Consider it done. But I also wanted to ask…", "topic": "TALK_BONE_SEER" }, { "text": "Where should I start?", "topic": "TALK_MISSION_ADVICE_SEER" }, @@ -301,13 +301,13 @@ { "id": "TALK_MISSION_ADVICE_SEER", "type": "talk_topic", - "dynamic_line": "The shambling corpses we see all around move in discord. Their song can be used, but for an Acolyte, this would be needlessly hard. Be sure to carve an unspoiled living creature.", + "dynamic_line": "The shambling corpses we see all around move in discord. Their song can be used, but for an Acolyte, this would be needlessly hard. Be sure to carve an unspoiled living creature.", "responses": [ { "text": "So, a creature that isn't a zombie, or a monster. Got it.", "topic": "TALK_NONE" } ] }, { "id": "TALK_SHARE_EQUIPMENT_SEER", "type": "talk_topic", - "dynamic_line": "The path to enlightenment is for you to walk. For me to aid you would ultimately impede your progress and muddle your song.", + "dynamic_line": "The path to enlightenment is for you to walk. For me to aid you would ultimately impede your progress and muddle your song.", "responses": [ { "text": "I see. Very well then.", "topic": "TALK_NONE" } ] }, { @@ -316,7 +316,7 @@ "dynamic_line": { "u_has_trait": "seer_mark", "no": "Only those who bear my mark will prove themselves worthy of my skills.", - "yes": "You bear my mark, meaning I believe you have potential to learn to truly listen to the Song. Yes, I will lend my skills to you, for now." + "yes": "You bear my mark, meaning I believe you have potential to learn to truly listen to the Song. Yes, I will lend my skills to you, for now." }, "responses": [ { "text": "I see. Very well then.", "topic": "TALK_NONE", "condition": { "not": { "u_has_trait": "seer_mark" } } }, @@ -336,7 +336,7 @@ { "id": "TALK_MISSION_REJECTED_SEER", "type": "talk_topic", - "dynamic_line": "I understand your reluctancy. Feel free to return when you see the way.", + "dynamic_line": "I understand your reluctancy. Feel free to return when you see the way.", "responses": [ { "text": "Maybe some other time. Changing the topic…", "topic": "TALK_NONE" }, { "text": "Alright, but I have to go now.", "topic": "TALK_DONE" } @@ -345,7 +345,7 @@ { "type": "talk_topic", "id": "TALK_BONE_SEER_CYCLE", - "dynamic_line": "It's not just walking horrors and monsters that have changed with the Cataclysm. It started a… cycle, of sorts. Everything repeats. We can only see it in others, but it happens to us, even you and I. How many times have you fallen? Your flesh rent from your body, devoured. Or perhaps it was the quiet whimper of death to exposure. But your bones rose again. Different flesh, different name, sometimes even different knowledge, but the bones, the same. We are all trapped in the same cycle. We just keep forgetting. That's why we need to amass the Song. That's why it has to end, even if it means the destruction, not restoration.", + "dynamic_line": "It's not just walking horrors and monsters that have changed with the Cataclysm. It started a… cycle, of sorts. Everything repeats. We can only see it in others, but it happens to us, even you and I. How many times have you fallen? Your flesh rent from your body, devoured. Or perhaps it was the quiet whimper of death to exposure. But your bones rose again. Different flesh, different name, sometimes even different knowledge, but the bones, the same. We are all trapped in the same cycle. We just keep forgetting. That's why we need to amass the Song. That's why it has to end, even if it means the destruction, not restoration.", "responses": [ { "text": "That is… that's really one hell of a belief. Well, if it helps you deal with the world, who am I to argue.", diff --git a/data/json/npcs/TALK_ALLY_TUTORIAL.json b/data/json/npcs/TALK_ALLY_TUTORIAL.json index 0f3b82d484c34..6e34b80f5725d 100644 --- a/data/json/npcs/TALK_ALLY_TUTORIAL.json +++ b/data/json/npcs/TALK_ALLY_TUTORIAL.json @@ -110,7 +110,7 @@ { "id": "TALK_ALLY_TUTORIAL_ACTIVITIES", "type": "talk_topic", - "dynamic_line": "I can help with some tasks if you show me where to work.\n Use the zone manager (keybind 'Y') to set up sorting zones for your loot, or to draw blueprints for a building, or to define where you want to plant some crops, or where you'd like some trees cut down, or where you want a vehicle dismantled or repaired, or a good fishing spot. Then talk to me about my current activity and tell me to sort stuff, or build stuff, or cut down trees, or repair or dismantle a vehicle, or do farmwork, or catch some fish, and I'll go off and do my best to get what you want done.\n If I need tools, you should leave them in a loot zone near where you want me to work - axes for logging, shovels and seeds and fertilizer for farming, wrenches and hacksaws or a toolbox to take apart a vehicle. I promise to put stuff back in an unsorted loot zone when I'm finished.\n I can pretty much sort out our stuff without needing tools, but keep the piles of unsorted and sorted stuff kind of close together because I don't want to walk back and forth carrying junk too much.", + "dynamic_line": "I can help with some tasks if you show me where to work.\n Use the zone manager (keybind 'Y') to set up sorting zones for your loot, or to draw blueprints for a building, or to define where you want to plant some crops, or where you'd like some trees cut down, or where you want a vehicle dismantled or repaired, or a good fishing spot. Then talk to me about my current activity and tell me to sort stuff, or build stuff, or cut down trees, or repair or dismantle a vehicle, or do farmwork, or catch some fish, and I'll go off and do my best to get what you want done.\n If I need tools, you should leave them in a loot zone near where you want me to work - axes for logging, shovels and seeds and fertilizer for farming, wrenches and hacksaws or a toolbox to take apart a vehicle. I promise to put stuff back in an unsorted loot zone when I'm finished.\n I can pretty much sort out our stuff without needing tools, but keep the piles of unsorted and sorted stuff kind of close together because I don't want to walk back and forth carrying junk too much.", "responses": [ { "text": "Good to know. Can you perform first aid?", "topic": "TALK_ALLY_TUTORIAL_MEDIC" }, { "text": "What about carrying stuff in general?", "topic": "TALK_ALLY_TUTORIAL_MULE" }, diff --git a/data/json/npcs/TALK_CITY_COP.json b/data/json/npcs/TALK_CITY_COP.json index a2ad99073acdb..03d6ccabf40e0 100644 --- a/data/json/npcs/TALK_CITY_COP.json +++ b/data/json/npcs/TALK_CITY_COP.json @@ -7,7 +7,7 @@ "type": "dialogue", "context": "survivor_cop", "value": "yes", - "no": "STOP, Put your hands in the air! Ha, startled you didn't I…there is no law anymore...", + "no": "STOP, Put your hands in the air! Ha, startled you didn't I… there is no law anymore…", "yes": "Hi there, ." }, "responses": [ @@ -25,7 +25,7 @@ { "type": "talk_topic", "id": "TALK_CITY_COP_INTRO", - "dynamic_line": "I was watching the station when things went sideways. None of the other officers returned from the last call, well not as humans anyway...", + "dynamic_line": "I was watching the station when things went sideways. None of the other officers returned from the last call, well not as humans anyway…", "responses": [ { "text": "Why don't you go somewhere else?", "topic": "TALK_CITY_COP_LEAVE" }, { "text": "Let's trade then.", "effect": "start_trade", "topic": "TALK_CITY_COP" }, diff --git a/data/json/npcs/TALK_COMMON_ALLY.json b/data/json/npcs/TALK_COMMON_ALLY.json index 893f2ab47a465..2e3dbe78a391e 100644 --- a/data/json/npcs/TALK_COMMON_ALLY.json +++ b/data/json/npcs/TALK_COMMON_ALLY.json @@ -13,12 +13,12 @@ "no": { "npc_need": "fatigue", "level": "TIRED", - "no": "Just few minutes more...", + "no": "Just few minutes more…", "yes": "Make it quick, I want to go back to sleep." }, "yes": "Just let me sleep, !" }, - "yes": "No, just no..." + "yes": "No, just no…" }, "no": "Anything to do before I go to sleep?" }, @@ -904,7 +904,7 @@ }, { "is_day": "Well, it's the time of day for a quick break surely! How are you holding up?", - "no": "Man it's dark out isn't it? what's up?" + "no": "Man it's dark out isn't it? what's up?" }, { "npc_has_effect": "infected", diff --git a/data/json/npcs/TALK_COMMON_GREET.json b/data/json/npcs/TALK_COMMON_GREET.json index 1be7967e15d8e..b59242d6d8e2f 100644 --- a/data/json/npcs/TALK_COMMON_GREET.json +++ b/data/json/npcs/TALK_COMMON_GREET.json @@ -82,7 +82,7 @@ { "id": "TALK_STRANGER_WARY", "type": "talk_topic", - "dynamic_line": "Okay, no sudden movements...", + "dynamic_line": "Okay, no sudden movements…", "responses": [ { "text": "Bye.", "topic": "TALK_DONE" } ] }, { diff --git a/data/json/npcs/TALK_COMMON_OTHER.json b/data/json/npcs/TALK_COMMON_OTHER.json index de6a348c8db12..53d8d0028c216 100644 --- a/data/json/npcs/TALK_COMMON_OTHER.json +++ b/data/json/npcs/TALK_COMMON_OTHER.json @@ -72,7 +72,7 @@ "no": "Why should I travel with you?", "yes": "You asked me recently; ask again later." }, - "yes": "Not until I get some antibiotics..." + "yes": "Not until I get some antibiotics…" }, "responses": [ { @@ -225,7 +225,7 @@ "no": { "npc_has_effect": "asked_to_train", "no": "I have some reason for denying you training.", - "yes": "Give it some time, I'll show you something new later..." + "yes": "Give it some time, I'll show you something new later…" }, "yes": "I'm too tired, let me rest first." }, @@ -264,7 +264,7 @@ { "id": "TALK_FRIEND_UNCOMFORTABLE", "type": "talk_topic", - "dynamic_line": "I really don't feel comfortable doing so...", + "dynamic_line": "I really don't feel comfortable doing so…", "responses": [ { "text": "I'll give you some space.", "topic": "TALK_FRIEND" } ] }, { @@ -361,7 +361,7 @@ { "id": "TALK_STOLE_ITEM", "type": "talk_topic", - "dynamic_line": "You picked up something that does not belong to you...", + "dynamic_line": "You picked up something that does not belong to you…", "responses": [ { "text": "Okay, okay, this is all a misunderstanding. Sorry, I'll drop it now.", diff --git a/data/json/npcs/TALK_CYBORG_1.json b/data/json/npcs/TALK_CYBORG_1.json index c8bf7001283c5..9adf354fdc2bc 100644 --- a/data/json/npcs/TALK_CYBORG_1.json +++ b/data/json/npcs/TALK_CYBORG_1.json @@ -7,8 +7,8 @@ "type": "dialogue", "context": "cyborg", "value": "yes", - "no": "I… I'm free. *Zzzt* I'm actually free! *bzzz* Look, you're the first person I've seen in a long time.", - "yes": "Hey again. *kzzz*" + "no": "I… I'm free. *Zzzt* I'm actually free! *bzzz* Look, you're the first person I've seen in a long time.", + "yes": "Hey again. *kzzz*" }, "speaker_effect": { "effect": { "npc_add_var": "cyborg_has_talked", "type": "dialogue", "context": "cyborg", "value": "yes" } }, "responses": [ @@ -45,7 +45,7 @@ { "id": "TALK_CYBORG_FRIENDLY", "type": "talk_topic", - "dynamic_line": "*buzz* Great! So what happens now?", + "dynamic_line": "*buzz* Great! So what happens now?", "responses": [ { "text": "Come with me. We can help each other out.", @@ -59,7 +59,7 @@ { "id": "TALK_CYBORG_WARY", "type": "talk_topic", - "dynamic_line": "...Wait. *BEEP* Why do I believe you? *ZZZT* You could be just as bad as them!", + "dynamic_line": "…Wait. *BEEP* Why do I believe you? *ZZZT* You could be just as bad as them!", "responses": [ { "text": "I wouldn't have pulled your chip out if I didn't want you to think for yourself.", @@ -79,7 +79,7 @@ { "id": "TALK_CYBORG_FEARFUL", "type": "talk_topic", - "dynamic_line": "Okay, okay, *BUZZ* I'm sorry! Don't hurt me again! Anything but the chip!", + "dynamic_line": "Okay, okay, *BUZZ* I'm sorry! Don't hurt me again! Anything but the chip!", "responses": [ { "text": "Follow me and do my bidding, then.", @@ -104,7 +104,7 @@ { "id": "TALK_CYBORG_BREAKDOWN", "type": "talk_topic", - "dynamic_line": "...kill… *ZTZTZT* …you!", + "dynamic_line": "…kill… *ZTZTZT* …you!", "responses": [ { "text": "Run while you still can!", diff --git a/data/json/npcs/TALK_FRIEND_CONVERSATION.json b/data/json/npcs/TALK_FRIEND_CONVERSATION.json index d1561687f2bc6..d903a0ef0fbf3 100644 --- a/data/json/npcs/TALK_FRIEND_CONVERSATION.json +++ b/data/json/npcs/TALK_FRIEND_CONVERSATION.json @@ -2,7 +2,7 @@ { "id": "TALK_CONVERSATION_DANGER", "type": "talk_topic", - "dynamic_line": "Are you sure? This doesn't seem like a particularly safe place for small talk...", + "dynamic_line": "Are you sure? This doesn't seem like a particularly safe place for small talk…", "responses": [ { "text": "It's fine, we've got a moment.", diff --git a/data/json/npcs/TALK_MARLOSS_VOICE.json b/data/json/npcs/TALK_MARLOSS_VOICE.json index f27f620e9820e..b3ba9b7efbd8a 100644 --- a/data/json/npcs/TALK_MARLOSS_VOICE.json +++ b/data/json/npcs/TALK_MARLOSS_VOICE.json @@ -18,7 +18,7 @@ "May you find your peace, traveler.", "We might have lost everything, but hope remains.", "May the earth flourish beneath our paths.", - "Unity of spirit, of mind, and body...", + "Unity of spirit, of mind, and body…", "Look for the bonds which define you, and act in accord." ], "responses": [ diff --git a/data/json/npcs/TALK_NC_FARMER.json b/data/json/npcs/TALK_NC_FARMER.json index 6523b82c20560..acce03aaa0496 100644 --- a/data/json/npcs/TALK_NC_FARMER.json +++ b/data/json/npcs/TALK_NC_FARMER.json @@ -82,7 +82,7 @@ { "type": "talk_topic", "id": "TALK_NC_FARMER_EXPERTISE", - "dynamic_line": "I grew up on the farm, I don't know much about ghosts and goblins, but I've spent a lot of time growing food and I work hard. It's better in the country, cleaner. Not as dangerous. I hope.", + "dynamic_line": "I grew up on the farm, I don't know much about ghosts and goblins, but I've spent a lot of time growing food and I work hard. It's better in the country, cleaner. Not as dangerous. I hope.", "responses": [ { "text": "Why don't you go somewhere else?", "topic": "TALK_NC_FARMER_LEAVE" }, { "text": "Wanna get outta here?", "topic": "TALK_SUGGEST_FOLLOW" }, diff --git a/data/json/npcs/TALK_TRUE_FOODPERSON.json b/data/json/npcs/TALK_TRUE_FOODPERSON.json index dddd7c3b0391b..126759d4d3ab3 100644 --- a/data/json/npcs/TALK_TRUE_FOODPERSON.json +++ b/data/json/npcs/TALK_TRUE_FOODPERSON.json @@ -135,7 +135,7 @@ { "id": "TALK_FOODPERSON_INTRODUCTION", "type": "talk_topic", - "dynamic_line": "Indeed it is I! The one and only FOODPERSON!", + "dynamic_line": "Indeed it is I! The one and only FOODPERSON!", "responses": [ { "text": "Wow! Such an honor to meet you in person!", diff --git a/data/json/npcs/isherwood_farm/NPC_Carlos_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Carlos_Isherwood.json index 5eb1f6b9f4c65..b884653ed51b2 100644 --- a/data/json/npcs/isherwood_farm/NPC_Carlos_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Carlos_Isherwood.json @@ -151,7 +151,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_CARLOS_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "I heard about Barry, can you tell me what captured him?", diff --git a/data/json/npcs/isherwood_farm/NPC_Chris_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Chris_Isherwood.json index 3a1722506f42c..14b09df676204 100644 --- a/data/json/npcs/isherwood_farm/NPC_Chris_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Chris_Isherwood.json @@ -144,7 +144,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_CHRIS_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "Your dad asked me to come find you, said you've been looking for your uncle.", diff --git a/data/json/npcs/isherwood_farm/NPC_Eddie_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Eddie_Isherwood.json index bdd946365427f..945369f171555 100644 --- a/data/json/npcs/isherwood_farm/NPC_Eddie_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Eddie_Isherwood.json @@ -181,7 +181,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_EDDIE_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "Your son helps with the dairy?", "topic": "TALK_EDDIE_LUKE" }, { "text": "So, Jesse runs the horse farm?", "topic": "TALK_EDDIE_JESSE" }, diff --git a/data/json/npcs/isherwood_farm/NPC_Jack_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Jack_Isherwood.json index 1942f5f8f8420..8f98a076cf814 100644 --- a/data/json/npcs/isherwood_farm/NPC_Jack_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Jack_Isherwood.json @@ -258,7 +258,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_JACK_TOPICS", - "dynamic_line": "Go on ...", + "dynamic_line": "Go on…", "responses": [ { "text": "I'm here to deliver some resources.", diff --git a/data/json/npcs/isherwood_farm/NPC_Jesse_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Jesse_Isherwood.json index 20fa52bb87b22..a09209e1eb02e 100644 --- a/data/json/npcs/isherwood_farm/NPC_Jesse_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Jesse_Isherwood.json @@ -170,7 +170,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_JESSE_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "Looks like you are doing well here.", "topic": "TALK_ISHERWOOD_JESSE_TALK1" }, { "text": "Do you have any animal care tips?", "topic": "TALK_ISHERWOOD_JESSE_TIPS" }, diff --git a/data/json/npcs/isherwood_farm/NPC_Lisa_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Lisa_Isherwood.json index bc9966c1d2a9d..bf0cc45c3d7d0 100644 --- a/data/json/npcs/isherwood_farm/NPC_Lisa_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Lisa_Isherwood.json @@ -123,7 +123,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_LISA_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "Hi, I'm looking for Jesse.", "topic": "TALK_LISA_JESSE" }, { "text": "Hi, I'm looking for Chris.", "topic": "TALK_LISA_CHRIS" }, diff --git a/data/json/npcs/isherwood_farm/NPC_Luke_Isherwood.json b/data/json/npcs/isherwood_farm/NPC_Luke_Isherwood.json index bd77065d5a349..6e7206e5d2658 100644 --- a/data/json/npcs/isherwood_farm/NPC_Luke_Isherwood.json +++ b/data/json/npcs/isherwood_farm/NPC_Luke_Isherwood.json @@ -142,7 +142,7 @@ { "type": "talk_topic", "id": "TALK_ISHERWOOD_LUKE_TOPICS", - "dynamic_line": "Go on...", + "dynamic_line": "Go on…", "responses": [ { "text": "Must be tough having the world fall apart when you had you future to look forward to.", diff --git a/data/json/npcs/missiondef.json b/data/json/npcs/missiondef.json index 882496f30c7ac..9ae846640a61e 100644 --- a/data/json/npcs/missiondef.json +++ b/data/json/npcs/missiondef.json @@ -731,10 +731,10 @@ "dialogue": { "describe": "It's hard to tell who actually has the skills to survive these days…", "offer": "It's hard surviving out here on our own, and we'd probably have a better chance working together. Problem is, I don't really know you and what you're capable of. You might have what it takes, or you might not. Either way, I'm going to need some proof. Come back in a few days and I'll gladly follow you. It's basically a win-win for me: either you come back and I'll know you've got what it takes, or you don't and I'll know that I was right not to follow you.", - "accepted": "I'll see you then…or I won't, and then I'll know I made the right decision.", + "accepted": "I'll see you then… or I won't, and then I'll know I made the right decision.", "rejected": "Ya, it was a long shot I admit.", "advice": "Don't die. If you're asking me for advice, that doesn't bode well for you.", - "inquire": "Well, you're not dead…yet.", + "inquire": "Well, you're not dead… yet.", "success": "I'll be honest, I wasn't really expecting to see you again. A promise is a promise, I'll follow you now!", "success_lie": "I know time is relative and all that.", "failure": "I'm not quite sure how you failed to survive AND are talking to me." diff --git a/data/json/npcs/refugee_center/beggars/BEGGAR_5_Yusuke_Taylor.json b/data/json/npcs/refugee_center/beggars/BEGGAR_5_Yusuke_Taylor.json index 141ff4165be2a..837720dc4240b 100644 --- a/data/json/npcs/refugee_center/beggars/BEGGAR_5_Yusuke_Taylor.json +++ b/data/json/npcs/refugee_center/beggars/BEGGAR_5_Yusuke_Taylor.json @@ -100,7 +100,7 @@ { "type": "talk_topic", "id": "TALK_REFUGEE_BEGGAR_5_FUR", - "dynamic_line": "Gross, isn't it? Feels like pubes. I just started growing it everywhere a little while after the Cataclysm. No idea what caused it. I can't blame them for hating it, I hate it.", + "dynamic_line": "Gross, isn't it? Feels like pubes. I just started growing it everywhere a little while after the Cataclysm. No idea what caused it. I can't blame them for hating it, I hate it.", "responses": [ { "text": "Why live out here?", "topic": "TALK_REFUGEE_BEGGAR_5_TALK2" }, { diff --git a/data/json/npcs/refugee_center/surface_refugees/NPC_Draco_Dune.json b/data/json/npcs/refugee_center/surface_refugees/NPC_Draco_Dune.json index 3557e2c7f2738..374bca1837018 100644 --- a/data/json/npcs/refugee_center/surface_refugees/NPC_Draco_Dune.json +++ b/data/json/npcs/refugee_center/surface_refugees/NPC_Draco_Dune.json @@ -150,7 +150,7 @@ { "type": "talk_topic", "id": "TALK_REFUGEE_Draco_3", - "dynamic_line": "Oh you don't have time for all that, do you? Well, I'll give you the short version. I've gotten kinda tired of it in the telling. Frankly, it's not as heroic, not as inspiring, not as tragic, and certainly not as funny as some of the tales around here. But it's mine, ya know? I'm a musician. Guitar's my baby. You like folk and the blues, friend? Well, that was my bag and I sure could please my own ear with em, anyway. Folks who's bein' generous might also say it pleased theirs. Problem is, I seem to be between guitars right now, you know? Temporarily guitar-light, if you get my saying. Problem is, in the run for my life, I had to use old Jasmine as a bit of a billy club. Had to curb some rowdy dudes on my way here. It was her or me, you understand? You wouldn't begrudge a man breakin' his instrument to save his life, would ya?", + "dynamic_line": "Oh you don't have time for all that, do you? Well, I'll give you the short version. I've gotten kinda tired of it in the telling. Frankly, it's not as heroic, not as inspiring, not as tragic, and certainly not as funny as some of the tales around here. But it's mine, ya know? I'm a musician. Guitar's my baby. You like folk and the blues, friend? Well, that was my bag and I sure could please my own ear with em, anyway. Folks who's bein' generous might also say it pleased theirs. Problem is, I seem to be between guitars right now, you know? Temporarily guitar-light, if you get my saying. Problem is, in the run for my life, I had to use old Jasmine as a bit of a billy club. Had to curb some rowdy dudes on my way here. It was her or me, you understand? You wouldn't begrudge a man breakin' his instrument to save his life, would ya?", "responses": [ { "text": "I think I would've done the same. Nobody around here has a guitar?", "topic": "TALK_REFUGEE_Draco_4" }, { "text": "Yes, yes I would… you monster.", "topic": "TALK_DONE" } diff --git a/data/json/npcs/refugee_center/surface_refugees/NPC_Pablo_Nunez.json b/data/json/npcs/refugee_center/surface_refugees/NPC_Pablo_Nunez.json index dcca034326a96..54c8e6059c60e 100644 --- a/data/json/npcs/refugee_center/surface_refugees/NPC_Pablo_Nunez.json +++ b/data/json/npcs/refugee_center/surface_refugees/NPC_Pablo_Nunez.json @@ -144,7 +144,7 @@ { "type": "talk_topic", "id": "TALK_REFUGEE_Pablo_Background2", - "dynamic_line": "Dana and I were evacuated early, because of her pregnancy. They took us to a concentration center, and then we got on a bus to come here. The bus though, it was rolled over by a giant monster, and many died. We made it out along with a few others, and we kept going until we made it here. It wasn't much farther, and for some reason the monster didn't chase us, just kept tearing at the bus.", + "dynamic_line": "Dana and I were evacuated early, because of her pregnancy. They took us to a concentration center, and then we got on a bus to come here. The bus though, it was rolled over by a giant monster, and many died. We made it out along with a few others, and we kept going until we made it here. It wasn't much farther, and for some reason the monster didn't chase us, just kept tearing at the bus.", "responses": [ { "text": "What about the pregnancy?", "topic": "TALK_REFUGEE_Pablo_Background2_pregnancy" }, { "text": "What happened to the other crash survivors?", "topic": "TALK_REFUGEE_Pablo_Background2_survivors" }, diff --git a/data/json/npcs/refugee_center/surface_refugees/NPC_Rhyzaea_Johnny.json b/data/json/npcs/refugee_center/surface_refugees/NPC_Rhyzaea_Johnny.json index f9d92d96dea22..e211e7e563265 100644 --- a/data/json/npcs/refugee_center/surface_refugees/NPC_Rhyzaea_Johnny.json +++ b/data/json/npcs/refugee_center/surface_refugees/NPC_Rhyzaea_Johnny.json @@ -113,7 +113,7 @@ { "type": "talk_topic", "id": "TALK_REFUGEE_Rhyzaea_Background", - "dynamic_line": "It's a long, long story. I'm not from around here, I'm actually from way out in Western Canada. I'd always wanted to see New England, and I was down here on vacation when, well, you know. I got evacuated, but because I'm not a US citizen they weren't willing to take me downstairs. I can understand that, even if I don't like it much. To tell you the truth I'm still coming to terms with the fact that I'll probably never know how my family and my band are doing.", + "dynamic_line": "It's a long, long story. I'm not from around here, I'm actually from way out in Western Canada. I'd always wanted to see New England, and I was down here on vacation when, well, you know. I got evacuated, but because I'm not a US citizen they weren't willing to take me downstairs. I can understand that, even if I don't like it much. To tell you the truth I'm still coming to terms with the fact that I'll probably never know how my family and my band are doing.", "responses": [ { "text": "Tell me about yourself.", "topic": "TALK_REFUGEE_Rhyzaea_Background2" }, { "text": "Tell me about your family.", "topic": "TALK_REFUGEE_Rhyzaea_Family" }, diff --git a/data/json/npcs/refugee_center/surface_refugees/NPC_Stan_Borichenko.json b/data/json/npcs/refugee_center/surface_refugees/NPC_Stan_Borichenko.json index 55349288b0141..454e105f1cd9c 100644 --- a/data/json/npcs/refugee_center/surface_refugees/NPC_Stan_Borichenko.json +++ b/data/json/npcs/refugee_center/surface_refugees/NPC_Stan_Borichenko.json @@ -76,7 +76,7 @@ "type": "general", "context": "meeting", "value": "yes", - "yes": [ "Hi.", "Hello.", "Hm? Oh, hi.", "...Hi." ], + "yes": [ "Hi.", "Hello.", "Hm? Oh, hi.", "…Hi." ], "no": "Hello. I'm sorry, if we've met before, I don't really remember. I'm… I'm Stan." }, "responses": [ diff --git a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_broker.json b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_broker.json index d27d188c43c2b..f579c93e2cfde 100644 --- a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_broker.json +++ b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_broker.json @@ -163,7 +163,7 @@ "context": "recruit", "value": "yes", "yes": "I do. I don't know what you did to convince them to move out, but our supply chain and I both thank you. I hope it wasn't too unseemly.", - "no": "Even once we got things sorted out, there weren't enough beds for everyone, and definitely not enough supplies. These are harsh times. We're doing what we can for those folks… at least they've got shelter." + "no": "Even once we got things sorted out, there weren't enough beds for everyone, and definitely not enough supplies. These are harsh times. We're doing what we can for those folks… at least they've got shelter." } }, { @@ -175,7 +175,7 @@ { "type": "talk_topic", "id": "TALK_FREE_MERCHANT_STOCKS_SEALED1wrong", - "dynamic_line": "We didn't have great organization when we first arrived. A few of the earliest arrivals set up a triage and sorting system, with the sick and infirm getting set aside to wait. It's cruel, but we could see there was only space for so many, and we didn't know what was causing people to turn into zombies at the time, so we were trying to quarantine out infection. A couple folks died in there, and it escalated. One of the first people here, Jacob, had taken charge of the whole thing. When the triage area had to be evacuated he stayed behind to make sure everyone who could get out got out. It was a hell of a loss.", + "dynamic_line": "We didn't have great organization when we first arrived. A few of the earliest arrivals set up a triage and sorting system, with the sick and infirm getting set aside to wait. It's cruel, but we could see there was only space for so many, and we didn't know what was causing people to turn into zombies at the time, so we were trying to quarantine out infection. A couple folks died in there, and it escalated. One of the first people here, Jacob, had taken charge of the whole thing. When the triage area had to be evacuated he stayed behind to make sure everyone who could get out got out. It was a hell of a loss.", "speaker_effect": [ { "effect": { "u_add_var": "told_about_FM_evacuation", "type": "general", "context": "conversation", "value": "yes" } } ], diff --git a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_guard_generic.json b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_guard_generic.json index 7c5306be2a3f2..3a5a09be2e9d5 100644 --- a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_guard_generic.json +++ b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_guard_generic.json @@ -14,7 +14,7 @@ "id": "TALK_GUARD", "type": "talk_topic", "dynamic_line": [ - "I'm not in charge here, you're looking for someone else...", + "I'm not in charge here, you're looking for someone else…", "Keep civil or I'll bring the pain.", "Just on watch, move along.", { diff --git a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_shopkeep.json b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_shopkeep.json index 0d4c57d67424f..c549babbe622e 100644 --- a/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_shopkeep.json +++ b/data/json/npcs/refugee_center/surface_staff/NPC_free_merchant_shopkeep.json @@ -257,7 +257,7 @@ { "id": "TALK_EVAC_MERCHANT", "type": "talk_topic", - "dynamic_line": { "u_is_wearing": "badge_marshal", "yes": "Welcome marshal...", "no": "Welcome..." } + "dynamic_line": { "u_is_wearing": "badge_marshal", "yes": "Welcome marshal…", "no": "Welcome…" } }, { "id": "TALK_EVAC_MERCHANT_NEW", diff --git a/data/json/npcs/refugee_center/surface_staff/NPC_old_guard_doctor.json b/data/json/npcs/refugee_center/surface_staff/NPC_old_guard_doctor.json index 1bad332985496..dd4421cb5b79e 100644 --- a/data/json/npcs/refugee_center/surface_staff/NPC_old_guard_doctor.json +++ b/data/json/npcs/refugee_center/surface_staff/NPC_old_guard_doctor.json @@ -15,7 +15,7 @@ { "id": "TALK_SCIENCE_REP", "type": "talk_topic", - "dynamic_line": { "u_has_any_trait": [ "PROF_FED" ], "yes": "Marshal...", "no": "Citizen..." }, + "dynamic_line": { "u_has_any_trait": [ "PROF_FED" ], "yes": "Marshal…", "no": "Citizen…" }, "responses": [ { "text": "Who are you?", "topic": "TALK_SCIENCE_REP_NEW" }, { "text": "Heard anything about the outside world?", "topic": "TALK_SCIENCE_REP_WORLD" }, diff --git a/data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json b/data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json index 347d8d2c097f6..d874374cf56a1 100644 --- a/data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json +++ b/data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json @@ -24,7 +24,7 @@ { "id": "TALK_OLD_GUARD_REP", "type": "talk_topic", - "dynamic_line": { "u_has_any_trait": [ "PROF_FED" ], "yes": "Marshal...", "no": "Citizen..." }, + "dynamic_line": { "u_has_any_trait": [ "PROF_FED" ], "yes": "Marshal…", "no": "Citizen…" }, "responses": [ { "text": "Who are you?", "topic": "TALK_OLD_GUARD_REP_NEW" }, { "text": "Heard anything about the outside world?", "topic": "TALK_OLD_GUARD_REP_WORLD" }, diff --git a/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json b/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json index 3ec807bd27bb0..c1c680f3700e5 100644 --- a/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +++ b/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json @@ -336,7 +336,7 @@ { "id": "TALK_ROBOFAC_INTERCOM_BUY_PROTECTIVE_GEAR", "type": "talk_topic", - "dynamic_line": "Given the current context, we are willing to sell you a set of our protective gear: gas mask, suit and gear, at a considerable discount. We will sell it for two of our coins.\n\nthe intercom: Hmm wait, we might not have your size...", + "dynamic_line": "Given the current context, we are willing to sell you a set of our protective gear: gas mask, suit and gear, at a considerable discount. We will sell it for two of our coins.\n\nthe intercom: Hmm wait, we might not have your size…", "responses": [ { "text": "[ 2 HGC ] Deal!", diff --git a/data/json/npcs/robofac/NPC_ROBOFAC_MERC_1.json b/data/json/npcs/robofac/NPC_ROBOFAC_MERC_1.json index 4d5df70e8b950..c9ebebb28b448 100644 --- a/data/json/npcs/robofac/NPC_ROBOFAC_MERC_1.json +++ b/data/json/npcs/robofac/NPC_ROBOFAC_MERC_1.json @@ -205,9 +205,9 @@ "id": "TALK_ROBOFAC_MERC_1_RANDOM_THOUGHTS", "type": "talk_topic", "dynamic_line": [ - "Thinking I should go hunt something soon...", - "Wondering if things will get better someday...", - "Hmm? Nothing, I guess I just like resting in this place.", + "Thinking I should go hunt something soon…", + "Wondering if things will get better someday…", + "Hmm? Nothing, I guess I just like resting in this place.", "Have you ever noticed how… wait no, never mind.", "I heard some strange dimensional resonance caused all this, do you think it has happened to other places?", "You noticed this place has working WI-FI? Well not the rest of the net works anyways." diff --git a/data/json/npcs/robofac/ROBOFAC_SURFACE_FREEMERCHANT.json b/data/json/npcs/robofac/ROBOFAC_SURFACE_FREEMERCHANT.json index c6a1d7bd1c294..ca60953a66160 100644 --- a/data/json/npcs/robofac/ROBOFAC_SURFACE_FREEMERCHANT.json +++ b/data/json/npcs/robofac/ROBOFAC_SURFACE_FREEMERCHANT.json @@ -91,11 +91,11 @@ "dynamic_line": { "u_is_wearing": "badge_marshal", "yes": [ - "Still plenty of outlaws in the roads, perhaps you should tend to your job, marshal...", + "Still plenty of outlaws in the roads, perhaps you should tend to your job, marshal…", "You see anything you want, marshal?", "Oh, a U.S. marshal, how quaint." ], - "no": [ "Welcome...", "Here to trade, I hope?", "Safe travels, scavenger." ] + "no": [ "Welcome…", "Here to trade, I hope?", "Safe travels, scavenger." ] }, "responses": [ { "text": "Let's trade.", "effect": "start_trade", "topic": "TALK_ROBOFAC_FREE_MERCHANT" }, diff --git a/data/json/npcs/tacoma_ranch/NPC_ranch_barber.json b/data/json/npcs/tacoma_ranch/NPC_ranch_barber.json index 44d2152c5ec8c..823ffa9106c48 100644 --- a/data/json/npcs/tacoma_ranch/NPC_ranch_barber.json +++ b/data/json/npcs/tacoma_ranch/NPC_ranch_barber.json @@ -47,7 +47,7 @@ { "type": "talk_topic", "id": "TALK_RANCH_BARBER_CUT", - "dynamic_line": "Stand still while I get my clippers...", + "dynamic_line": "Stand still while I get my clippers…", "responses": [ { "text": "Thanks…", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/tacoma_ranch/NPC_ranch_guard.json b/data/json/npcs/tacoma_ranch/NPC_ranch_guard.json index d1af5c89f34c0..7e07ad2c3c409 100644 --- a/data/json/npcs/tacoma_ranch/NPC_ranch_guard.json +++ b/data/json/npcs/tacoma_ranch/NPC_ranch_guard.json @@ -14,7 +14,7 @@ "id": "TALK_RANCH_GUARD", "type": "talk_topic", "dynamic_line": [ - "I'm not in charge here, you're looking for someone else...", + "I'm not in charge here, you're looking for someone else…", "Keep civil or I'll bring the pain.", "Just on watch, move along.", { diff --git a/data/json/npcs/tacoma_ranch/NPC_ranch_sickly_laborer.json b/data/json/npcs/tacoma_ranch/NPC_ranch_sickly_laborer.json index fd43d2fa40cee..ec1e2cabc6805 100644 --- a/data/json/npcs/tacoma_ranch/NPC_ranch_sickly_laborer.json +++ b/data/json/npcs/tacoma_ranch/NPC_ranch_sickly_laborer.json @@ -13,7 +13,7 @@ { "type": "talk_topic", "id": "TALK_RANCH_ILL_1", - "dynamic_line": "Please leave me alone...", + "dynamic_line": "Please leave me alone…", "responses": [ { "text": "What is your job here?", "topic": "TALK_RANCH_ILL_1_JOB" }, { "text": "Do you need any help?", "topic": "TALK_RANCH_ILL_1_HIRE" }, @@ -30,13 +30,13 @@ { "type": "talk_topic", "id": "TALK_RANCH_ILL_1_HIRE", - "dynamic_line": "I don't know what you could do. I've tried everything. Just give me time...", + "dynamic_line": "I don't know what you could do. I've tried everything. Just give me time…", "responses": [ { "text": "OK.", "topic": "TALK_RANCH_ILL_1" } ] }, { "type": "talk_topic", "id": "TALK_RANCH_ILL_1_SICK", - "dynamic_line": "I keep getting sick! At first I thought it was something I ate but now it seems like I can't keep anything down...", + "dynamic_line": "I keep getting sick! At first I thought it was something I ate but now it seems like I can't keep anything down…", "responses": [ { "text": "Uhm.", "topic": "TALK_RANCH_ILL_1" } ] } ] diff --git a/data/mods/Aftershock/npcs/prepnet_dialogue.json b/data/mods/Aftershock/npcs/prepnet_dialogue.json index d95f96b172d71..2ce76101afdca 100644 --- a/data/mods/Aftershock/npcs/prepnet_dialogue.json +++ b/data/mods/Aftershock/npcs/prepnet_dialogue.json @@ -94,7 +94,7 @@ { "type": "talk_topic", "id": "TALK_PrepNet_gardener_ask_goods", - "dynamic_line": "Here? Fruits and berries. Maybe the occasional piece of farm equipment, but you need crypto coins", + "dynamic_line": "Here? Fruits and berries. Maybe the occasional piece of farm equipment, but you need crypto coins", "responses": [ { "text": "Ok.", "topic": "TALK_PrepNet_gardener_1" }, { diff --git a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json index fb1bef2dd2977..9ad99814f7dd3 100644 --- a/data/mods/DinoMod/NPC/NC_BO_BARONYX.json +++ b/data/mods/DinoMod/NPC/NC_BO_BARONYX.json @@ -41,7 +41,7 @@ "type": "dialogue", "context": "first_meeting", "value": "yes", - "no": "You look hungry friend. So much hunger in this world. This is the time of the eaters.", + "no": "You look hungry friend. So much hunger in this world. This is the time of the eaters.", "yes": { "u_has_var": "asked_about_eating", "type": "dialogue", @@ -219,7 +219,7 @@ { "id": "TALK_MISSION_ACCEPTED_SWAMPER", "type": "talk_topic", - "dynamic_line": "Excellent. Make it happen.", + "dynamic_line": "Excellent. Make it happen.", "responses": [ { "text": "Consider it done. But I also wanted to ask…", "topic": "TALK_SWAMPER" }, { "text": "Where should I start?", "topic": "TALK_MISSION_ADVICE_SWAMPER" }, diff --git a/data/mods/Magiclysm/npc/TALK_OLD_MAGUS.json b/data/mods/Magiclysm/npc/TALK_OLD_MAGUS.json index 4c4066e4b998a..5ee961b6072d0 100644 --- a/data/mods/Magiclysm/npc/TALK_OLD_MAGUS.json +++ b/data/mods/Magiclysm/npc/TALK_OLD_MAGUS.json @@ -7,7 +7,7 @@ "type": "dialogue", "context": "old_magus", "value": "yes", - "no": "Huh? *mumble mumble* … Who are you?", + "no": "Huh? *mumble mumble* … Who are you?", "yes": "Oh, you again." }, "responses": [ @@ -52,7 +52,7 @@ { "type": "talk_topic", "id": "TALK_OLD_MAGUS_LEAVE", - "dynamic_line": "And leave my tower and all my research? I think not.", + "dynamic_line": "And leave my tower and all my research? I think not.", "responses": [ { "text": "Wanna get outta here?", "topic": "TALK_SUGGEST_FOLLOW" }, { "text": "What can you sell me?", "topic": "TALK_OLD_MAGUS", "effect": "start_trade" }, diff --git a/src/dialogue.h b/src/dialogue.h index 4f5921be746c0..401c02459990b 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -332,7 +332,7 @@ struct dynamic_line_t { public: dynamic_line_t() = default; - dynamic_line_t( const std::string &line ); + dynamic_line_t( const translation &line ); dynamic_line_t( const JsonObject &jo ); dynamic_line_t( const JsonArray &ja ); static dynamic_line_t from_member( const JsonObject &jo, const std::string &member_name ); diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 2723d0657e06f..dc02ddef94c2e 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -2948,26 +2948,31 @@ dynamic_line_t dynamic_line_t::from_member( const JsonObject &jo, const std::str } else if( jo.has_object( member_name ) ) { return dynamic_line_t( jo.get_object( member_name ) ); } else if( jo.has_string( member_name ) ) { - return dynamic_line_t( jo.get_string( member_name ) ); + translation line; + jo.read( member_name, line ); + return dynamic_line_t( line ); } else { return dynamic_line_t{}; } } -dynamic_line_t::dynamic_line_t( const std::string &line ) +dynamic_line_t::dynamic_line_t( const translation &line ) { function = [line]( const dialogue & ) { - return _( line ); + return line.translated(); }; } + dynamic_line_t::dynamic_line_t( const JsonObject &jo ) { if( jo.has_member( "and" ) ) { std::vector lines; for( const JsonValue entry : jo.get_array( "and" ) ) { if( entry.test_string() ) { - lines.emplace_back( entry.get_string() ); + translation line; + entry.read( line ); + lines.emplace_back( line ); } else if( entry.test_array() ) { lines.emplace_back( entry.get_array() ); } else if( entry.test_object() ) { @@ -2995,6 +3000,11 @@ dynamic_line_t::dynamic_line_t( const JsonObject &jo ) }; } else if( jo.has_string( "gendered_line" ) ) { const std::string line = jo.get_string( "gendered_line" ); + if( test_mode ) { + // HACK: check text style by reading it as a translation object + translation dummy; + jo.read( "gendered_line", dummy ); + } if( !jo.has_array( "relevant_genders" ) ) { jo.throw_error( R"(dynamic line with "gendered_line" must also have "relevant_genders")" ); @@ -3051,7 +3061,9 @@ dynamic_line_t::dynamic_line_t( const JsonArray &ja ) std::vector lines; for( const JsonValue entry : ja ) { if( entry.test_string() ) { - lines.emplace_back( entry.get_string() ); + translation line; + entry.read( line ); + lines.emplace_back( line ); } else if( entry.test_array() ) { lines.emplace_back( entry.get_array() ); } else if( entry.test_object() ) { From 28dcbe6ac74937e86757b90e275777da27857c0f Mon Sep 17 00:00:00 2001 From: Fris0uman <41293484+Fris0uman@users.noreply.github.com> Date: Mon, 29 Jun 2020 08:22:32 +0200 Subject: [PATCH 18/41] No healing for you Sugar (#41651) * Sugar constructs don't heal * Prevent use of incompatible healing items --- data/mods/My_Sweet_Cataclysm/sweet_mutations.json | 4 ++-- doc/JSON_FLAGS.md | 1 + src/character.cpp | 6 ++++-- src/game.cpp | 3 +++ src/item_action.cpp | 2 +- src/player.cpp | 5 +++++ 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/data/mods/My_Sweet_Cataclysm/sweet_mutations.json b/data/mods/My_Sweet_Cataclysm/sweet_mutations.json index b56219f0ac8ce..6cf1e1159746b 100644 --- a/data/mods/My_Sweet_Cataclysm/sweet_mutations.json +++ b/data/mods/My_Sweet_Cataclysm/sweet_mutations.json @@ -35,7 +35,7 @@ "vitamin_rates": [ [ "vitC", -900 ], [ "vitB", -900 ], [ "vitA", -900 ], [ "iron", -900 ], [ "calcium", -900 ] ], "starting_trait": true, "healing_awake": 0.0, - "healing_resting": 0.0, + "healing_resting": -1.0, "healthy_rate": 0.0, "bleed_resist": 1000, "fat_to_max_hp": 0.1, @@ -49,6 +49,6 @@ "bash": 5 } ], - "flags": [ "NO_THIRST", "NO_DISEASE", "NO_RADIATION" ] + "flags": [ "NO_THIRST", "NO_DISEASE", "NO_RADIATION", "NO_MINIMAL_HEALING" ] } ] diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index bf473494ac671..c12ac74a150b0 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -1114,6 +1114,7 @@ Also see `monster_attacks.json` for more special attacks, for example, impale an - ```NO_DISEASE``` This mutation grants immunity to diseases. - ```NO_THIRST``` Your thirst is not modified by food or drinks. - ```NO_RADIATION``` This mutation grants immunity to radiations. +- ```NO_MINIMAL_HEALING``` This mutation disables the minimal healing of 1 hp a day. ### Categories diff --git a/src/character.cpp b/src/character.cpp index 80955b7c4fb0c..3f4a2c628cfa6 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -4690,7 +4690,7 @@ void Character::update_body( const time_point &from, const time_point &to ) // TODO: change @ref med to take time_duration mend( five_mins * to_turns( 5_minutes ) ); } - if( ticks_between( from, to, 24_hours ) > 0 ) { + if( ticks_between( from, to, 24_hours ) > 0 && !has_trait_flag( "NO_MINIMAL_HEALING" ) ) { enforce_minimum_healing(); } @@ -7665,7 +7665,9 @@ bool Character::invoke_item( item *used, const std::string &method ) bool Character::invoke_item( item *used, const std::string &method, const tripoint &pt ) { - if( !has_enough_charges( *used, true ) ) { + if( !has_enough_charges( *used, true ) || ( used->is_medication() && + !can_use_heal_item( *used ) ) ) { + add_msg_if_player( m_bad, _( "Your biology is not compatible with that healing item." ) ); return false; } diff --git a/src/game.cpp b/src/game.cpp index 6f7f853c8e19b..3cdea2d048f75 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2104,6 +2104,9 @@ static hint_rating rate_action_use( const avatar &you, const item &it ) return hint_rating::good; } } else if( it.is_food() || it.is_medication() || it.is_book() || it.is_armor() ) { + if( it.is_medication() && !you.can_use_heal_item( it ) ) { + return hint_rating::cant; + } // The rating is subjective, could be argued as hint_rating::cant or hint_rating::good as well return hint_rating::iffy; } else if( it.type->has_use() ) { diff --git a/src/item_action.cpp b/src/item_action.cpp index d9b773b4917c0..dc93f78f2cef2 100644 --- a/src/item_action.cpp +++ b/src/item_action.cpp @@ -261,7 +261,7 @@ void game::item_action_menu() kmenu.text = _( "Execute which action?" ); kmenu.input_category = "ITEM_ACTIONS"; input_context ctxt( "ITEM_ACTIONS" ); - for( const auto &id : item_actions ) { + for( const std::pair &id : item_actions ) { ctxt.register_action( id.first, id.second.name ); kmenu.additional_actions.emplace_back( id.first, id.second.name ); } diff --git a/src/player.cpp b/src/player.cpp index 1b5f20a8ce0d7..0cd7bc9e53cfb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -3011,6 +3011,11 @@ void player::use( item_location loc ) item &used = *loc; last_item = used.typeId(); + if( ( *loc ).is_medication() && !can_use_heal_item( *loc ) ) { + add_msg_if_player( m_bad, _( "Your biology is not compatible with that healing item." ) ); + return; + } + if( used.is_tool() ) { if( !used.type->has_use() ) { add_msg_if_player( _( "You can't do anything interesting with your %s." ), used.tname() ); From af418c9a58be30cfd675c44747f07388c81ef792 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Sun, 28 Jun 2020 23:34:59 -0700 Subject: [PATCH 19/41] Move TALK_COMMON_ALLY options into submenus (#41593) --- data/json/npcs/TALK_COMMON_ALLY.json | 190 +++++++++---------- data/json/npcs/TALK_FRIEND_CONVERSATION.json | 50 +++++ 2 files changed, 138 insertions(+), 102 deletions(-) diff --git a/data/json/npcs/TALK_COMMON_ALLY.json b/data/json/npcs/TALK_COMMON_ALLY.json index 2e3dbe78a391e..b1845426208b7 100644 --- a/data/json/npcs/TALK_COMMON_ALLY.json +++ b/data/json/npcs/TALK_COMMON_ALLY.json @@ -46,7 +46,71 @@ "responses": [ { "text": "I want to give you some commands for combat.", "topic": "TALK_COMBAT_COMMANDS" }, { "text": "I want to set some miscellaneous rules.", "topic": "TALK_MISC_RULES" }, + { + "text": "I'd like to know a bit more about your abilities.", + "topic": "TALK_FRIEND", + "effect": "reveal_stats" + }, + { "text": "There's something I want you to do.", "topic": "TALK_ALLY_ORDERS" }, + { "text": "I just wanted to talk for a bit.", "topic": "TALK_ALLY_SOCIAL" }, + { "text": "Can you help me understand something? (HELP/TUTORIAL)", "topic": "TALK_ALLY_TUTORIAL" }, + { "text": "I'm going to go my own way for a while.", "topic": "TALK_LEAVE" }, + { "text": "Let's go.", "topic": "TALK_DONE" } + ] + }, + { + "id": [ "TALK_ALLY_SOCIAL" ], + "type": "talk_topic", + "dynamic_line": { + "is_by_radio": " *tshk* Are you serious? This isn't a cell phone. Can it wait until we're in the same place?", + "no": "Sure, what did you want to say?" + }, + "responses": [ + { + "text": "Mind if we just chat for a bit about your history?", + "topic": "TALK_FRIEND_CONVERSATION", + "condition": { + "and": [ "at_safe_space", { "or": [ { "npc_has_trait_flag": "BG_SURVIVAL_STORY" }, { "npc_has_trait": "NPC_STATIC_NPC" } ] } ] + }, + "//": "If the NPC already has a BG story, or started out as a static NPC (and so probably doesn't need a random bg story), then go on.", + "switch": true + }, + { + "text": "Mind if we just chat for a bit about your history?", + "topic": "TALK_FRIEND_CONVERSATION", + "condition": "at_safe_space", + "switch": true, + "effect": { "npc_add_trait": "BGSS_Confused_1" }, + "//": "If the NPC doesn't have a BG survival story flagged trait, and didn't start the game as a static NPC, give them a BG story.", + "//2": "This is a stand-in for some kind of better system to add a random trait." + }, + { + "text": "Mind if we just chat for a bit about your history?", + "topic": "TALK_CONVERSATION_DANGER", + "condition": { "not": "at_safe_space" }, + "switch": true + }, + { + "text": "Mind if we just chat for a bit about your history?", + "topic": "TALK_CONVERSATION_RADIO", + "condition": { "not": "is_by_radio" }, + "switch": true + }, + { + "text": "Let's just chitchat for a while, I could use some relaxation.", + "topic": "TALK_FRIEND_CHAT", + "condition": { "not": { "npc_has_effect": "asked_to_socialize" } } + }, { "text": "Can I do anything for you?", "topic": "TALK_MISSION_LIST" }, + { "text": "I changed my mind, wanted to ask you something else.", "topic": "TALK_NONE" }, + { "text": "Let's go.", "topic": "TALK_DONE" } + ] + }, + { + "id": [ "TALK_ALLY_ORDERS" ], + "type": "talk_topic", + "dynamic_line": [ "I'm all ears, my friend.", "You gonna give me orders?", "What would you like?", "Just say the word." ], + "responses": [ { "text": "Can you teach me anything?", "condition": { "not": "is_by_radio" }, @@ -66,13 +130,6 @@ "success": { "topic": "TALK_DENY_TRAIN" }, "failure": { "topic": "TALK_TRAIN_PERSUADE" } }, - { - "text": "Let's trade items", - "topic": "TRADE_HALLU", - "condition": { "npc_has_trait": "HALLUCINATION" }, - "switch": true, - "default": false - }, { "text": "Let's trade items.", "condition": { "not": "is_by_radio" }, @@ -81,6 +138,13 @@ "switch": true, "default": true }, + { + "text": "Let's trade items", + "topic": "TRADE_HALLU", + "condition": { "npc_has_trait": "HALLUCINATION" }, + "switch": true, + "default": false + }, { "text": "I want you to use this item.", "condition": { "not": "is_by_radio" }, @@ -105,8 +169,6 @@ "topic": "TALK_FRIEND_GUARD", "effect": "assign_camp" }, - { "text": "Let's talk about your current activity.", "topic": "TALK_ACTIVITIES" }, - { "text": "Let's talk about faction camps.", "topic": "TALK_CAMP_GENERAL" }, { "text": "Find a horse and mount up!", "condition": { "not": "npc_is_riding" }, @@ -126,58 +188,32 @@ "effect": "goto_location" }, { - "text": "I'd like to know a bit more about your abilities.", - "topic": "TALK_FRIEND", - "effect": "reveal_stats" - }, - { - "text": "Any hints about the world we now live in?", - "trial": { - "type": "CONDITION", - "condition": { - "or": [ - { "npc_need": "thirst", "amount": 80 }, - { "npc_need": "hunger", "amount": 160 }, - { "npc_need": "fatigue", "level": "TIRED" }, - { "npc_has_effect": "asked_to_hint" }, - "u_driving", - "npc_driving" - ] - } - }, - "success": { "topic": "TALK_SHELTER_DENY_ADVICE" }, - "failure": { "topic": "TALK_SHELTER_ADVICE", "effect": { "npc_add_effect": "asked_to_hint", "duration": 300 } } - }, - { - "text": "Mind if we just chat for a bit about your history?", - "topic": "TALK_FRIEND_CONVERSATION", - "condition": { - "and": [ "at_safe_space", { "or": [ { "npc_has_trait_flag": "BG_SURVIVAL_STORY" }, { "npc_has_trait": "NPC_STATIC_NPC" } ] } ] - }, - "//": "If the NPC already has a BG story, or started out as a static NPC (and so probably doesn't need a random bg story), then go on.", + "text": "I want you to build a camp here.", + "topic": "TALK_HALLU_CAMP", + "condition": { "npc_has_trait": "HALLUCINATION" }, "switch": true }, { - "text": "Mind if we just chat for a bit about your history?", - "topic": "TALK_FRIEND_CONVERSATION", - "condition": "at_safe_space", + "text": "I want you to build a camp here.", + "topic": "TALK_DONE", + "effect": "start_camp", + "condition": { "npc_at_om_location": "FACTION_CAMP_START" }, "switch": true, - "effect": { "npc_add_trait": "BGSS_Confused_1" }, - "//": "If the NPC doesn't have a BG survival story flagged trait, and didn't start the game as a static NPC, give them a BG story.", - "//2": "This is a stand-in for some kind of better system to add a random trait." + "default": true }, { - "text": "Mind if we just chat for a bit about your history?", - "topic": "TALK_CONVERSATION_DANGER", - "condition": { "not": "at_safe_space" } + "text": "We need to abandon this camp.", + "condition": { "npc_at_om_location": "FACTION_CAMP_ANY" }, + "topic": "TALK_DONE", + "effect": "abandon_camp" }, { - "text": "Let's just chitchat for a while, I could use some relaxation.", - "topic": "TALK_FRIEND_CHAT", - "condition": { "not": { "npc_has_effect": "asked_to_socialize" } } + "text": "Show me what needs to be done at the camp.", + "topic": "TALK_DONE", + "effect": "basecamp_mission", + "condition": { "npc_at_om_location": "FACTION_CAMP_ANY" } }, - { "text": "Tell me about giving you orders (NPC TUTORIAL).", "topic": "TALK_ALLY_TUTORIAL" }, - { "text": "I'm going to go my own way for a while.", "topic": "TALK_LEAVE" }, + { "text": "Let's talk about your current activity.", "topic": "TALK_ACTIVITIES" }, { "text": "Let's go.", "topic": "TALK_DONE" } ] }, @@ -883,56 +919,6 @@ "dynamic_line": "Sure thing, I'll make my way there.", "responses": [ { "text": "Affirmative.", "topic": "TALK_DONE" } ] }, - { - "id": "TALK_FRIEND_CHAT", - "type": "talk_topic", - "dynamic_line": [ - { "u_has_item": "beer", "yes": "", "no": "" }, - { "u_has_item": "european_pilsner", "yes": "", "no": "" }, - { "u_has_item": "pale_ale", "yes": "", "no": "" }, - { "u_has_item": "india_pale_ale", "yes": "", "no": "" }, - { "u_has_item": "wine_barley", "yes": "", "no": "" }, - { - "is_season": "summer", - "yes": "Yeah, this summer heat is hitting me hard, let's take a quick break, how goes it ?", - "no": "" - }, - { - "is_season": "winter", - "yes": "OK, maybe it'll stop me from freezing in this weather, what's up?", - "no": "" - }, - { - "is_day": "Well, it's the time of day for a quick break surely! How are you holding up?", - "no": "Man it's dark out isn't it? what's up?" - }, - { - "npc_has_effect": "infected", - "yes": "Well, I'm feeling pretty sick… are you doing OK though?", - "no": "" - }, - { - "has_no_assigned_mission": "", - "no": { - "has_many_assigned_missions": "Definitely, by the way, thanks for helping me so much with my tasks! Anyway, you coping OK, ? ", - "no": "OK, let's take a moment, oh, and thanks for helping me with that thing, so… what's up?" - } - }, - { - "days_since_cataclysm": 30, - "yes": "Now, we've got a moment, I was just thinking it's been a month or so since… since all this, how are you coping with it all?", - "no": "" - } - ], - "responses": [ - { - "text": "Oh you know, not bad, not bad…", - "topic": "TALK_DONE", - "switch": true, - "effect": [ "morale_chat_activity", { "npc_add_effect": "asked_to_socialize", "duration": 7000 } ] - } - ] - }, { "id": "TRADE_HALLU", "type": "talk_topic", diff --git a/data/json/npcs/TALK_FRIEND_CONVERSATION.json b/data/json/npcs/TALK_FRIEND_CONVERSATION.json index d903a0ef0fbf3..0d25832db6c5b 100644 --- a/data/json/npcs/TALK_FRIEND_CONVERSATION.json +++ b/data/json/npcs/TALK_FRIEND_CONVERSATION.json @@ -28,5 +28,55 @@ "type": "talk_topic", "dynamic_line": "What did you want to talk about?", "responses": [ { "text": "Actually, never mind.", "topic": "TALK_NONE" } ] + }, + { + "id": "TALK_FRIEND_CHAT", + "type": "talk_topic", + "dynamic_line": [ + { "u_has_item": "beer", "yes": "", "no": "" }, + { "u_has_item": "european_pilsner", "yes": "", "no": "" }, + { "u_has_item": "pale_ale", "yes": "", "no": "" }, + { "u_has_item": "india_pale_ale", "yes": "", "no": "" }, + { "u_has_item": "wine_barley", "yes": "", "no": "" }, + { + "is_season": "summer", + "yes": "Yeah, this summer heat is hitting me hard, let's take a quick break, how goes it ?", + "no": "" + }, + { + "is_season": "winter", + "yes": "OK, maybe it'll stop me from freezing in this weather, what's up?", + "no": "" + }, + { + "is_day": "Well, it's the time of day for a quick break surely! How are you holding up?", + "no": "Man it's dark out isn't it? What's up?" + }, + { + "npc_has_effect": "infected", + "yes": "Well, I'm feeling pretty sick… are you doing OK though?", + "no": "" + }, + { + "has_no_assigned_mission": "", + "no": { + "has_many_assigned_missions": "Definitely, by the way, thanks for helping me so much with my tasks! Anyway, you coping OK, ? ", + "no": "OK, let's take a moment, oh, and thanks for helping me with that thing, so… what's up?" + } + }, + { + "days_since_cataclysm": 30, + "yes": "Now, we've got a moment, I was just thinking it's been a month or so since… since all this, how are you coping with it all?", + "no": "" + } + ], + "responses": [ + { + "text": "Oh you know, not bad, not bad…", + "topic": "TALK_DONE", + "switch": true, + "effect": [ "morale_chat_activity", { "npc_add_effect": "asked_to_socialize", "duration": 7000 } ] + } + ] } ] From 2f386b3bafefd97679e0d30cf38e15077102364d Mon Sep 17 00:00:00 2001 From: LyleSY Date: Mon, 29 Jun 2020 02:36:26 -0400 Subject: [PATCH 20/41] Add tigers (#41659) --- data/json/mapgen/zoo.json | 4 ++-- data/json/monstergroups/mammal.json | 3 ++- data/json/monstergroups/misc.json | 6 ++++-- data/json/monsters/mammal.json | 16 ++++++++++++++++ data/json/monsters/zed-animal.json | 14 ++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/data/json/mapgen/zoo.json b/data/json/mapgen/zoo.json index 33bdde5fd27df..6cb543524d36a 100644 --- a/data/json/mapgen/zoo.json +++ b/data/json/mapgen/zoo.json @@ -139,8 +139,8 @@ { "chance": 75, "item": "vending_drink", "x": 20, "y": 1 } ], "place_monster": [ - { "monster": "mon_coyote", "x": 8, "y": 16 }, - { "monster": "mon_coyote", "x": 9, "y": 17 }, + { "monster": "mon_tiger", "x": 8, "y": 16 }, + { "monster": "mon_tiger", "x": 9, "y": 17 }, { "monster": "mon_bear", "x": 8, "y": 20 } ] } diff --git a/data/json/monstergroups/mammal.json b/data/json/monstergroups/mammal.json index a0bcab9009071..72138773b29eb 100644 --- a/data/json/monstergroups/mammal.json +++ b/data/json/monstergroups/mammal.json @@ -119,7 +119,8 @@ { "monster": "mon_cat_sphynx", "freq": 50, "cost_multiplier": 0 }, { "monster": "mon_cat_sphynx_kitten", "freq": 5, "cost_multiplier": 0 }, { "monster": "mon_cat_chonker", "freq": 50, "cost_multiplier": 0 }, - { "monster": "mon_cat_chonker_kitten", "freq": 5, "cost_multiplier": 0 } + { "monster": "mon_cat_chonker_kitten", "freq": 5, "cost_multiplier": 0 }, + { "monster": "mon_tiger", "freq": 1, "cost_multiplier": 30 } ] } ] diff --git a/data/json/monstergroups/misc.json b/data/json/monstergroups/misc.json index 19c1b4e05059c..b3b5b4718c62c 100644 --- a/data/json/monstergroups/misc.json +++ b/data/json/monstergroups/misc.json @@ -47,7 +47,8 @@ { "monster": "mon_zombie_pig", "freq": 10, "cost_multiplier": 25, "starts": 2160, "pack_size": [ 1, 5 ] }, { "monster": "mon_giant_cockroach", "freq": 10, "cost_multiplier": 1, "pack_size": [ 1, 5 ] }, { "monster": "mon_pregnant_giant_cockroach", "freq": 1, "cost_multiplier": 3 }, - { "monster": "mon_giant_cockroach_nymph", "freq": 5, "cost_multiplier": 1 } + { "monster": "mon_giant_cockroach_nymph", "freq": 5, "cost_multiplier": 1 }, + { "monster": "mon_tiger", "freq": 1, "cost_multiplier": 30 } ] }, { @@ -171,7 +172,8 @@ { "monster": "mon_dog_zombie_rot", "freq": 15, "cost_multiplier": 3 }, { "monster": "mon_squirrel", "freq": 1, "cost_multiplier": 0 }, { "monster": "mon_cat", "freq": 10, "cost_multiplier": 0 }, - { "monster": "mon_dog", "freq": 10, "cost_multiplier": 0 } + { "monster": "mon_dog", "freq": 10, "cost_multiplier": 0 }, + { "monster": "mon_tiger", "freq": 1, "cost_multiplier": 30 } ] } ] diff --git a/data/json/monsters/mammal.json b/data/json/monsters/mammal.json index 87f3bf37ed61f..520375c618e54 100644 --- a/data/json/monsters/mammal.json +++ b/data/json/monsters/mammal.json @@ -576,6 +576,22 @@ "BLEED" ] }, + { + "id": "mon_tiger", + "type": "MONSTER", + "name": { "str": "tiger" }, + "copy-from": "mon_cougar", + "description": "The majestic tiger, a large feline predator. Native to Asia, they are now most populous in private reserves in the United States. Fast and powerful, this predator is one of the most recognizable and beloved animals in the world. Also one of the deadliest.", + "volume": "190 L", + "weight": "190 kg", + "hp": 180, + "speed": 140, + "symbol": "T", + "morale": 60, + "melee_dice": 3, + "dodge": 2, + "zombify_into": "mon_ziger" + }, { "id": "mon_cow_calf", "type": "MONSTER", diff --git a/data/json/monsters/zed-animal.json b/data/json/monsters/zed-animal.json index d8d8510b57d81..5a26d8b249761 100644 --- a/data/json/monsters/zed-animal.json +++ b/data/json/monsters/zed-animal.json @@ -380,6 +380,20 @@ "FILTHY" ] }, + { + "id": "mon_ziger", + "type": "MONSTER", + "name": { "str": "Tiger wight" }, + "description": "This otherwise normal looking tiger stumbles and sways, its jaws slack, its eyes wide open and shining black.", + "copy-from": "mon_zougar", + "volume": "150 L", + "weight": "190 kg", + "hp": 200, + "speed": 110, + "symbol": "T", + "melee_dice": 3, + "dodge": 0 + }, { "id": "mon_zpider_mass", "type": "MONSTER", From 5699db334d2e737285a74b7467726b208f0676d2 Mon Sep 17 00:00:00 2001 From: Sage Barton Date: Mon, 29 Jun 2020 01:55:20 -0500 Subject: [PATCH 21/41] Fix Segmentation Fault When Removing Last Part Of Vehicle (#41660) --- src/veh_interact.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 4b2436563f857..051bb37277794 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -3185,6 +3185,7 @@ void veh_interact::complete_vehicle( player &p ) } else { veh->remove_part( vehicle_part ); veh->part_removal_cleanup(); + g->m.update_vehicle_cache( veh, veh->sm_pos.z ); } // This will be part of an NPC "job" where they need to clean up the acitivty items afterwards if( p.is_npc() ) { @@ -3196,7 +3197,6 @@ void veh_interact::complete_vehicle( player &p ) // point because we don't want to put them back into the vehicle part // that just got removed). put_into_vehicle_or_drop( p, item_drop_reason::deliberate, resulting_items ); - g->m.update_vehicle_cache( veh, veh->sm_pos.z ); break; } } From bda0d169607daae54b0a814a40173852f46f1c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Karlsson?= Date: Mon, 29 Jun 2020 14:50:30 +0200 Subject: [PATCH 22/41] Add longest_side to musical_instruments.json --- data/json/items/tool/musical_instruments.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/data/json/items/tool/musical_instruments.json b/data/json/items/tool/musical_instruments.json index 6dab2a0ea80fb..341ebe3e6ec42 100644 --- a/data/json/items/tool/musical_instruments.json +++ b/data/json/items/tool/musical_instruments.json @@ -7,6 +7,7 @@ "description": "A standard factory-made banjo. Looks to be in working condition.", "weight": "2000 g", "volume": "3 L", + "longest_side": "95 cm", "price": 7500, "price_postapoc": 500, "to_hit": 2, @@ -37,6 +38,7 @@ "description": "A polished bone flute with five finger holes.", "weight": "250 g", "volume": "500 ml", + "longest_side": "35 cm", "price": 5000, "price_postapoc": 100, "bashing": 2, @@ -67,6 +69,7 @@ "description": "An ornate clarinet made from wood.", "weight": "550 g", "volume": "1500 ml", + "longest_side": "60 cm", "price": 5500, "price_postapoc": 250, "to_hit": 1, @@ -97,6 +100,7 @@ "description": "A simple silver-plated flute.", "weight": "250 g", "volume": "500 ml", + "longest_side": "66 cm", "price": 5000, "price_postapoc": 150, "bashing": 2, @@ -126,6 +130,7 @@ "description": "A brass trumpet with only a few dents here and there.", "weight": "1500 g", "volume": "2500 ml", + "longest_side": "50 cm", "price": 7500, "price_postapoc": 300, "to_hit": 1, @@ -154,8 +159,9 @@ "category": "tools", "name": { "str": "ukulele" }, "description": "A small factory made ukulele. Looks to be in working condition.", - "weight": "2000 g", + "weight": "350 g", "volume": "2500 ml", + "longest_side": "55 cm", "price": 7500, "price_postapoc": 250, "to_hit": 2, @@ -186,6 +192,7 @@ "description": "A cheap, factory-made violin with a built-in holder for a bow. Still produces a nice sound.", "weight": "1300 g", "volume": "2500 ml", + "longest_side": "60 cm", "price": 7500, "price_postapoc": 600, "to_hit": 2, @@ -216,6 +223,7 @@ "description": "A shiny golden fiddle, with a strange aura around it. You feel like it once belonged to the best there's ever been.", "weight": "13000 g", "volume": "2500 ml", + "longest_side": "60 cm", "price": 1000000, "price_postapoc": 1000, "to_hit": 2, From 4fb291b9f22bd741186e5d9b403c8bc8c86db60c Mon Sep 17 00:00:00 2001 From: Meladath Date: Mon, 29 Jun 2020 15:21:04 +0100 Subject: [PATCH 23/41] Add longest_side to S&W 500, increase holster and XL holster size --- data/json/items/armor/holster.json | 4 ++-- data/json/items/gun/500.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/data/json/items/armor/holster.json b/data/json/items/armor/holster.json index 4d5957bf5991d..a364dfdfa97dc 100644 --- a/data/json/items/armor/holster.json +++ b/data/json/items/armor/holster.json @@ -117,7 +117,7 @@ "min_item_volume": "300 ml", "max_contains_volume": "800 ml", "max_contains_weight": "2 kg", - "max_item_length": "25 cm", + "max_item_length": "30 cm", "moves": 50 } ], @@ -229,7 +229,7 @@ "min_item_volume": "750 ml", "max_contains_volume": "1250 ml", "max_contains_weight": "5 kg", - "max_item_length": "30 cm", + "max_item_length": "40 cm", "moves": 50 } ], diff --git a/data/json/items/gun/500.json b/data/json/items/gun/500.json index e47a5954d989d..30235ec66f3e6 100644 --- a/data/json/items/gun/500.json +++ b/data/json/items/gun/500.json @@ -49,6 +49,7 @@ "price_postapoc": 3500, "to_hit": -2, "bashing": 12, + "longest_side": "381 mm", "material": [ "steel", "plastic" ], "symbol": "(", "color": "light_gray", From 123ffb0d4f3dadb07b057d8ff34e4285f7ef02e7 Mon Sep 17 00:00:00 2001 From: meladath Date: Mon, 29 Jun 2020 21:54:36 +0100 Subject: [PATCH 24/41] Update longest_side to use feret diameter Thanks to LaVeyanFiend for pointing it out. Co-authored-by: LaVeyanFiend <51099123+LaVeyanFiend@users.noreply.github.com> --- data/json/items/gun/500.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/items/gun/500.json b/data/json/items/gun/500.json index 30235ec66f3e6..b8c13a7c5c5aa 100644 --- a/data/json/items/gun/500.json +++ b/data/json/items/gun/500.json @@ -49,7 +49,7 @@ "price_postapoc": 3500, "to_hit": -2, "bashing": 12, - "longest_side": "381 mm", + "longest_side": "407 mm", "material": [ "steel", "plastic" ], "symbol": "(", "color": "light_gray", From bdb04de0b892fc32fa87af678246292d9f93f18c Mon Sep 17 00:00:00 2001 From: Meladath Date: Mon, 29 Jun 2020 22:19:41 +0100 Subject: [PATCH 25/41] Increase volume and max size due to some more gun sizes XL holster can now contain exactly 1.5x the volume/length of the standard holster --- data/json/items/armor/holster.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/json/items/armor/holster.json b/data/json/items/armor/holster.json index a364dfdfa97dc..842700fbbd2bb 100644 --- a/data/json/items/armor/holster.json +++ b/data/json/items/armor/holster.json @@ -115,7 +115,7 @@ "pocket_type": "CONTAINER", "holster": true, "min_item_volume": "300 ml", - "max_contains_volume": "800 ml", + "max_contains_volume": "1000 ml", "max_contains_weight": "2 kg", "max_item_length": "30 cm", "moves": 50 @@ -227,9 +227,9 @@ "pocket_type": "CONTAINER", "holster": true, "min_item_volume": "750 ml", - "max_contains_volume": "1250 ml", + "max_contains_volume": "1500 ml", "max_contains_weight": "5 kg", - "max_item_length": "40 cm", + "max_item_length": "45 cm", "moves": 50 } ], From 487c6552371a10a927f32093d4e929b5da7111ae Mon Sep 17 00:00:00 2001 From: Meladath Date: Mon, 29 Jun 2020 22:21:40 +0100 Subject: [PATCH 26/41] Correct volume for S&W 500 --- data/json/items/gun/500.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/items/gun/500.json b/data/json/items/gun/500.json index b8c13a7c5c5aa..f73571776caa8 100644 --- a/data/json/items/gun/500.json +++ b/data/json/items/gun/500.json @@ -44,7 +44,7 @@ "name": { "str_sp": "S&W 500" }, "description": "The 5-shot Smith and Wesson 500 revolver fires the comparably-named .500 S&W Magnum. It's an impressive weapon.", "weight": "1960 g", - "volume": "750 ml", + "volume": "1307 ml", "price": 90000, "price_postapoc": 3500, "to_hit": -2, From 2831caa86b440d451b3b37b0bfc55ec3f9af8fb0 Mon Sep 17 00:00:00 2001 From: Eric Pierce Date: Sun, 28 Jun 2020 20:37:45 -0600 Subject: [PATCH 27/41] Give magazine_well or rigidity to battery tools For most tools that are substantially larger than their compatible batteries, make their battery compartment (MAGAZINE_WELL pocket) "rigid" so the tool does not increase in size when a battery is inserted. For medium-sized shop tools that typically have a protruding battery pack, such as the circular saw, cordless drill, and angle grinder, give a "magazine_well" volume large enough to hold 20-30% of the battery. For very large tools like the extractor and vacuum oven, since they have a range of compatible batteries up to 50 L in volume, I granted them a "magazine_well" substantial enough for most smaller batteries, while larger storage batteries will protrude and add to item volume. --- data/json/items/melee/bludgeons.json | 2 ++ data/json/items/melee/swords_and_blades.json | 5 +++++ data/json/items/tool/cooking.json | 11 +++++++++++ data/json/items/tool/electronics.json | 12 ++++++++++++ data/json/items/tool/fire.json | 1 + data/json/items/tool/lighting.json | 4 ++++ data/json/items/tool/misc.json | 4 ++++ data/json/items/tool/radio_tools.json | 5 +++++ data/json/items/tool/science.json | 19 +++++++++++++++++++ data/json/items/tool/smoking.json | 1 + data/json/items/tool/toileteries.json | 1 + data/json/items/tool/woodworking.json | 2 ++ data/json/items/tool/workshop.json | 10 ++++++++++ 13 files changed, 77 insertions(+) diff --git a/data/json/items/melee/bludgeons.json b/data/json/items/melee/bludgeons.json index af6379b698de3..239879519b5f8 100644 --- a/data/json/items/melee/bludgeons.json +++ b/data/json/items/melee/bludgeons.json @@ -1025,6 +1025,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1056,6 +1057,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/melee/swords_and_blades.json b/data/json/items/melee/swords_and_blades.json index 5ac895482fff9..0993ea0243b10 100644 --- a/data/json/items/melee/swords_and_blades.json +++ b/data/json/items/melee/swords_and_blades.json @@ -1148,6 +1148,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1171,6 +1172,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1194,6 +1196,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1657,6 +1660,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "500 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "heavy_battery_cell", "heavy_plus_battery_cell", "heavy_atomic_battery_cell", "heavy_disposable_cell" ] @@ -1782,6 +1786,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "200 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] diff --git a/data/json/items/tool/cooking.json b/data/json/items/tool/cooking.json index 8e627371380a3..a3aa05e6f0818 100644 --- a/data/json/items/tool/cooking.json +++ b/data/json/items/tool/cooking.json @@ -86,6 +86,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -242,6 +243,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -268,6 +270,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -367,6 +370,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -470,6 +474,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -565,6 +570,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -594,6 +600,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -681,6 +688,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -724,6 +732,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -988,6 +997,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1033,6 +1043,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/electronics.json b/data/json/items/tool/electronics.json index ea761e0df0e92..e687cdd3b0fde 100644 --- a/data/json/items/tool/electronics.json +++ b/data/json/items/tool/electronics.json @@ -36,6 +36,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -71,6 +72,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -112,6 +114,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -191,6 +194,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -225,6 +229,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -259,6 +264,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -304,6 +310,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "100 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ @@ -350,6 +357,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -385,6 +393,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -432,6 +441,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -475,6 +485,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -591,6 +602,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/fire.json b/data/json/items/tool/fire.json index ceee5a07ea3b2..142937578c0f3 100644 --- a/data/json/items/tool/fire.json +++ b/data/json/items/tool/fire.json @@ -18,6 +18,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/lighting.json b/data/json/items/tool/lighting.json index 2213ecebe391b..1897a087f53c4 100644 --- a/data/json/items/tool/lighting.json +++ b/data/json/items/tool/lighting.json @@ -165,6 +165,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -477,6 +478,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -600,6 +602,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -646,6 +649,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/misc.json b/data/json/items/tool/misc.json index 6a6e614a7bdbe..dc4ce3b901890 100644 --- a/data/json/items/tool/misc.json +++ b/data/json/items/tool/misc.json @@ -113,6 +113,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -149,6 +150,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -388,6 +390,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "2 L", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "heavy_battery_cell", "heavy_plus_battery_cell", "heavy_atomic_battery_cell", "heavy_disposable_cell" ] @@ -613,6 +616,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "rigid": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] diff --git a/data/json/items/tool/radio_tools.json b/data/json/items/tool/radio_tools.json index c359eb4f8b24c..d5e8de67d7b43 100644 --- a/data/json/items/tool/radio_tools.json +++ b/data/json/items/tool/radio_tools.json @@ -30,6 +30,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -60,6 +61,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -113,6 +115,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -158,6 +161,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -193,6 +197,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/science.json b/data/json/items/tool/science.json index 1d3d2736c6366..7324786c49992 100644 --- a/data/json/items/tool/science.json +++ b/data/json/items/tool/science.json @@ -57,6 +57,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -99,6 +100,7 @@ "holster": true, "max_contains_volume": "25 L", "max_contains_weight": "200 kg", + "//": "this tool is small and has no actual battery compartment, but can connect to large batteries.", "item_restriction": [ "battery_car", "battery_motorbike", "small_storage_battery", "medium_storage_battery", "storage_battery" ] } ] @@ -124,6 +126,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ "large_storage_battery", "storage_battery" ] @@ -159,6 +162,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ "large_storage_battery", "storage_battery" ] @@ -197,6 +201,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ "large_storage_battery", "storage_battery" ] @@ -224,6 +229,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ "large_storage_battery", "storage_battery" ] @@ -262,6 +268,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -313,6 +320,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -363,6 +371,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -414,6 +423,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "5 L", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -511,6 +521,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "500 ml", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -562,6 +573,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "500 ml", "max_contains_volume": "50 L", "max_contains_weight": "400 kg", "item_restriction": [ @@ -790,6 +802,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -825,6 +838,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -867,6 +881,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -909,6 +924,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -943,6 +959,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -977,6 +994,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1198,6 +1216,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/smoking.json b/data/json/items/tool/smoking.json index 30a563987eb74..c2baca0d5177b 100644 --- a/data/json/items/tool/smoking.json +++ b/data/json/items/tool/smoking.json @@ -20,6 +20,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/toileteries.json b/data/json/items/tool/toileteries.json index b341a20fc03cb..d6a91037f1cf2 100644 --- a/data/json/items/tool/toileteries.json +++ b/data/json/items/tool/toileteries.json @@ -52,6 +52,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", diff --git a/data/json/items/tool/woodworking.json b/data/json/items/tool/woodworking.json index 3d49e7dea2d4a..a20dabbe0f7c8 100644 --- a/data/json/items/tool/woodworking.json +++ b/data/json/items/tool/woodworking.json @@ -79,6 +79,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "200 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] @@ -163,6 +164,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "200 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] diff --git a/data/json/items/tool/workshop.json b/data/json/items/tool/workshop.json index e9096786566fa..ed256a47020e6 100644 --- a/data/json/items/tool/workshop.json +++ b/data/json/items/tool/workshop.json @@ -80,6 +80,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "200 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] @@ -201,6 +202,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -229,6 +231,7 @@ { "pocket_type": "MAGAZINE_WELL", "holster": true, + "magazine_well": "200 ml", "max_contains_volume": "20 L", "max_contains_weight": "20 kg", "item_restriction": [ "medium_battery_cell", "medium_plus_battery_cell", "medium_atomic_battery_cell", "medium_disposable_cell" ] @@ -433,6 +436,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -473,6 +477,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -711,6 +716,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -814,6 +820,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -852,6 +859,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1010,6 +1018,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", @@ -1049,6 +1058,7 @@ "pocket_data": [ { "pocket_type": "MAGAZINE_WELL", + "rigid": true, "holster": true, "max_contains_volume": "20 L", "max_contains_weight": "20 kg", From 07e837a53c91604f9a7248701241814ef9b68426 Mon Sep 17 00:00:00 2001 From: i-am-erk <45136638+I-am-Erk@users.noreply.github.com> Date: Mon, 29 Jun 2020 22:37:21 -0700 Subject: [PATCH 28/41] restore npc hints and faction camps to help file --- data/json/npcs/TALK_ALLY_TUTORIAL.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/data/json/npcs/TALK_ALLY_TUTORIAL.json b/data/json/npcs/TALK_ALLY_TUTORIAL.json index 6e34b80f5725d..cabdf3cb49029 100644 --- a/data/json/npcs/TALK_ALLY_TUTORIAL.json +++ b/data/json/npcs/TALK_ALLY_TUTORIAL.json @@ -6,6 +6,25 @@ "responses": [ { "text": "Forget I asked.", "topic": "TALK_FRIEND" }, { "text": "Skip it, let's get going.", "topic": "TALK_DONE" }, + { + "text": "Any hints about the world we now live in?", + "trial": { + "type": "CONDITION", + "condition": { + "or": [ + { "npc_need": "thirst", "amount": 80 }, + { "npc_need": "hunger", "amount": 160 }, + { "npc_need": "fatigue", "level": "TIRED" }, + { "npc_has_effect": "asked_to_hint" }, + "u_driving", + "npc_driving" + ] + } + }, + "success": { "topic": "TALK_SHELTER_DENY_ADVICE" }, + "failure": { "topic": "TALK_SHELTER_ADVICE", "effect": { "npc_add_effect": "asked_to_hint", "duration": 300 } } + }, + { "text": "Let's talk about faction camps.", "topic": "TALK_CAMP_GENERAL" }, { "text": "What do you mean, \"mostly\" willing to follow my lead?", "topic": "TALK_ALLY_TUTORIAL_MUTINY" }, { "text": "What's that about giving instructions?", "topic": "TALK_ALLY_TUTORIAL_TALK" }, { "text": "We can talk with radios?", "topic": "TALK_ALLY_TUTORIAL_RADIO" }, From d27578205f32815dce9c64813b5b0d6b4a4f0885 Mon Sep 17 00:00:00 2001 From: curstwist <39442864+curstwist@users.noreply.github.com> Date: Tue, 30 Jun 2020 03:05:22 -0400 Subject: [PATCH 29/41] Create Guide for intermediate mapgen.md (#41679) --- .../Guide for intermediate mapgen.md | 616 ++++++++++++++++++ 1 file changed, 616 insertions(+) create mode 100644 doc/JSON Mapping Guides/Guide for intermediate mapgen.md diff --git a/doc/JSON Mapping Guides/Guide for intermediate mapgen.md b/doc/JSON Mapping Guides/Guide for intermediate mapgen.md new file mode 100644 index 0000000000000..261496dc03af8 --- /dev/null +++ b/doc/JSON Mapping Guides/Guide for intermediate mapgen.md @@ -0,0 +1,616 @@ +**Intermediate Mapgen Guide:** + +This guide assumes you are comfortable with basic mapgen elements and adding regular mapgen. It is meant as a supplement to the mapgen.md and overmap.md documents. + +**This guide will cover:** + +* When to use nested mapgen vs. regular mapgen variants. +* How to make and spawn a nested map. +* Some nested map possibilities. +* NPC spawning. +* Leveraging existing nested maps for modders. +* Basic update_mapgen using traps. +* Merged maps for large buildings. + + +**Files you’ll use:** +* a new or existing file to hold your nested map entries (there is a sub folder in mapgen for nested map files). +* the mapgen file you want your nests to spawn in +* palette (optional) +* the files used in the beginner's tutorial (a mapgen file, overmap_terrain, and specials.json or multitile_city_buildings.json/regional_map_settings.json.) + +**Nested maps vs. variant maps:** + +Variant maps are mapgen files that completely replace another map variant by using the same `om_terrain name` and applying a `weight` entry to each variant for spawning in relation to each other. + +Nested maps are a new layer of map applied to an existing mapgen file. They can overwrite existing terrain, furniture, add spawns for loot, monsters, vehicles, etc. They can contain anything that a regular mapgen contains within the object entry. Nested maps are spawned by adding an entry into the main mapgen’s object entry. They can be any size from a single tile to the entire 24x24 overmap terrain. + +Both approaches offer advantages and disadvantages to adding variety to maps. + +Variants are good for large structural changes or complete overhauls. + +* For example, I may do a portion of a farm with a barn and another with a set of farm plots. +* If I want clearly different variants for an entire map, like the same house as empty, abandoned, and furnished. +* Before we added json roofs (and other linked z levels) to our mapgen, most buildings utilized variants for spawning, most have now been renamed but some variants still exist, especially in older specials. + +Nested maps are good for adding more targeted variety and randomness to maps. In addition to what the variant offers, nested maps can let you do things like: + +* rearrange the furniture in a room, or in every room on a case by case basis. +* add smaller targeted thematic content like set pieces, additional monsters, hidden rooms, rare spawns. +* Have different sets of loot and room themes that randomly spawn across multiple buildings. + + +**Update_mapgen:** + +Update mapgen is triggered during game play instead of being initialized during worldgen. I’ll cover some of the update_mapgen uses in this document but it deserves its own guide. + + * Traps can trigger mapgen changes. + * Allows missions to trigger mapgen changes. + * Used by the faction camp building system for blueprints along with nested maps. + * Used by map_extras. + +update mapgen maps are similar to nested maps but are applied to an existing map, not to the mapgen file. Like nested maps, they can overwrite existing terrain, furniture, add spawns for loot, monsters, vehicles, etc. They can contain anything that a regular mapgen contains within the object entry. They can be any size from a single tile to the entire 24x24 overmap terrain, and can even included nested mapgen objects. + +**Merged Maps** + +Merged maps are when you combine the mapgen entries for several OMTs into a single mapgen entry. The `rows` are combined for a group the maps. This is usually used for improved readability for the json and a more compact file size. They are generally handled the same as a single OMT mapgen, with a few exceptions included in this document. Like any mapgen option, there are tradeoffs, a notable limitation is the single fill_ter entry for multiple OMTs. + +**Creating Nested Maps:** + +You’ll want to make some choices before adding nested maps. + +* Their purpose, where are they spawning, multiple locations? +* If it is within a larger building, will you include doors/walls? +* What size map do you need to make. + +A nested map gives you the ability to overwrite or fill in a portion of an existing mapgen. The contents of the nested map entry can contain any entry within mapgen objects (excepting fill_ter). This includes adding nested maps inside your nested map for extra variability. + +Example json entry for the nested map: + +``` + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "room_9x9_recroom_E", + "//": "an entertainment area for various recreations", + "object": { + "mapgensize": [ 9, 9 ], + "rotation": [ 0, 3 ], + "rows": [ + "|||||||||", + "|HHH...=|", + "|Hl....x|", + "|%.....=|", + "|.A.A..&|", + "|JJ5JJ +", + "| |", + "|mVJ14 T|", + "|||||||||" + ], + "palettes": [ "standard_domestic_palette" ], + "terrain": { + ".": "t_carpet_green", + "H": "t_carpet_green", + "l": "t_carpet_green", + "A": "t_carpet_green", + "=": "t_carpet_green", + "x": "t_carpet_green", + "%": "t_carpet_green", + "&": "t_carpet_green" + }, + "furniture": { "%": "f_arcade_machine", "=": "f_speaker_cabinet", "&": "f_pinball_machine" }, + "place_loot": [ { "item": "stereo", "x": 7, "y": 2, "chance": 100 }, { "item": "laptop", "x": 5, "y": 5, "chance": 60 } ] + } + } + ``` + +This should feel pretty familiar since it looks like the `object` entry in mapgen and shares the same `type`. +Note the ID is now `nested_mapgen_id` and the object uses a new entry `mapgensize` + +* `nested_mapgen_id`: Your ID should provide useful information about the nest. Multiple nests can share the same ID. + +* `weight`: This value is new and most nested maps don't have it yet. It allows you to weight the spawns of nests that share the same `nested_mapgen_id` (aka variants of nests). + +* `mapgensize`: Nested mapgen can be any size from 1x1 to 24x24 but it must be square. You don't have to use every row or column of the `rows` entry. Any unused portions will fall back to the main mapgen. + +* `terrain` & `furniture`: Without `fill_ter`, you need to define every floor terrain under furniture. If you don't it will fall back to the main mapgen's `fill_ter`. In the above example, there's a green carpet in 1/2 the map and the rest picks up the floor of the mapgen (indoor concrete). If you need to overwrite existing furniture in the main mapgen you can use a combination of `t_null` and `f_null` to override preexisting mapgen. + +_Tips:_ +If you're doing interior spaces, pay attention to door placement and access pathways. + +* For walled nests, I generally keep the doors in the center of the walls. +* For open floor plan nests, I try to preserve the corner spaces for doors in the regular mapgen (if I can design the mapgen with the nests). + +example: note the corner tiles are all empty. +``` + "rows": [ + " CR ", + "O ", + " EE ", + " EE " + ], +``` + +example room outline with possible door placements. The `+` denotes any valid door placement for the above nest. This approach gives you the maximum number of possibilities for fitting this nest into enclosed rooms without blocking the doorway. I toss some indoor plants or other small furniture into the unused corners in the main mapgen as well, to fill out the rooms. + +``` + "rows": [ + "|+||+|", + "+ CR +", + "|O |", + "| EE |", + "+ EE +", + "|+||+|" + ], +``` + +Fitting nests into existing foundations/building outlines can be a bit of a puzzle, especially as you add variations that share the same ID or are used over many maps. So having your doors in predictable places in all your nests will aid in their re-use for future maps. + +We use a naming convention that includes the nested map size and some indication of its orientation or we add a comment with extra context in the json entry. + +Some ID's: +* room_9x9_recroom_N +* room_9x9_recroom_S +* 7x7_band_practice_open + + +by using room and a compass direction, it quickly identifies the nest as having walls/door and the door's orientation. The band practice one is an open space, no walls included. Including the map size will make searching, debug spawning and re-using nests easier as well. + + +**Debug testing:** + +So many nests, so hard to find ones to use! + +We've recently gotten the ability to spawn nested maps via debug in game and this is a huge help for making sure nests fit, don't conflict with elements in the existing maps and are oriented well without adjusting spawn weights to force the nest to spawn naturally. + +This is also a good way to "shop around" for existing nests to re-use in your maps. + +To debug spawn a nested map in game: +* Open debug menu (you will need to add a key bind) +* Choose `map` [m] +* Choose `spawn nested map` [n] +* Search list by using [/] +* Use your selector to place the nested map. The indicator is 0,0 coordinate of the nest. + +You'll quickly see why it's good to use a coherent name format. + +**Mini nests:** + +Nests can be as small as one tile which is very useful if you want special or rare spawns for items, monsters, vehicles, NPCs or other elements. + +An example of a spawn for a particular loot group: +These nests were used in a larger nest of a basement study. I didn't want the study to offer all the magiclysm class books at once. I made nests for each spell class item_group: + +3 1x1 nested maps that only include loot placement. They feed into a larger nest. + +``` + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "animist_loot_spawn", + "object": { "mapgensize": [ 1, 1 ], "place_loot": [ { "group": "animist_items", "x": 0, "y": 0, "chance": 70 } ] } + }, + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "magus_loot_spawn", + "object": { "mapgensize": [ 1, 1 ], "place_loot": [ { "group": "magus_items", "x": 0, "y": 0, "chance": 70 } ] } + }, + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "stormshaper_loot_spawn", + "object": { "mapgensize": [ 1, 1 ], "place_loot": [ { "group": "stormshaper_items", "x": 0, "y": 0, "chance": 70 } ] } + } + ``` + +**NPC spawning:** + +If you use `place_npc` on the main mapgen, the NPC will spawn 100% of the time. NPC's like the refugee center ones get placed like this. + +However, many NPCs should be closer to random encounters. The below example creates a nest that spawns an NPC (and only the NPC): + +``` + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "SEER_Brigitte_LaCroix_spawn", + "object": { "mapgensize": [ 1, 1 ], "place_npcs": [ { "class": "SEER_Brigitte_LaCroix", "x": 0, "y": 0 } ] } + } +``` + +You can also customize the surroundings in which the NPC spawns. For the Chef NPC that spawns in one restaurant, they get their survivor themed setting included: +Note the use of `t_null` in the majority of the map. A lot of the map is unused and relies on the main mapgen. It rearranges furniture to blockade the entrance and adds a little survivor's den flavor. +``` + { + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "chef_s_restaurant", + "object": { + "mapgensize": [ 13, 13 ], + "rows": [ + "mt_________#t", + "____________r", + "__________ffr", + "___________W_", + "_____________", + "_____________", + "_____________", + "_____________", + "_____________", + "_____________", + "_____________", + "_____________", + "_____________" + ], + "terrain": { "_": "t_null", "-": "t_wall", "W": "t_window_boarded" }, + "furniture": { "r": "f_rack", "f": "f_fridge", "t": "f_table", "#": "f_counter", "m": "f_makeshift_bed" }, + "place_npcs": [ { "class": "survivor_chef", "x": 5, "y": 1 } ], + "place_loot": [ + { "group": "produce", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "groce_meat", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "groce_dairyegg", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "bar_food", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "bar_fridge", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "jackets", "x": 0, "y": 0, "chance": 70, "repeat": [ 2, 3 ] }, + { "group": "alcohol_bottled_canned", "x": 1, "y": 0, "chance": 80 }, + { "group": "baked_goods", "x": [ 2, 4 ], "y": 2, "chance": 50, "repeat": [ 2, 3 ] }, + { "group": "groce_bread", "x": [ 2, 4 ], "y": 2, "chance": 50, "repeat": [ 2, 3 ] }, + { "group": "cannedfood", "x": [ 5, 6 ], "y": 0, "chance": 50, "repeat": [ 2, 3 ] }, + { "group": "cannedfood", "x": [ 9, 11 ], "y": 0, "chance": 50, "repeat": [ 2, 3 ] } + ] + } + } +``` + + **Spawning the nested maps** + + You can spawn nests in the usual two methods, using explicit symbol placement or x,y coordinates. I've encountered rare instances where one style works and the other doesn't but haven't pinned down the cause yet. + + + **x,y coordinate placement:** + +This adds some nice variability if you want the nest's spawn location to shift a bit around the map. I used this extensively on roofs since they are open spaces and I wanted to decrease how static they would feel otherwise. + + + In the main mapgen's `object` you enter the following entry: +``` + "place_nested": [ + { + "chunks": [ [ "null", 30 ], [ "roof_6x6_utility", 30 ], [ "roof_4x4_utility_1", 40 ] ], + "x": [ 5, 14 ], + "y": [ 14, 16 ] + } + ] +``` + +A NPC example: + +``` +"place_nested": [ { "chunks": [ [ "SEER_Brigitte_LaCroix_spawn", 20 ], [ "null", 80 ] ], "x": 18, "y": 6 } ] +``` + +The `chunks` are the `nested_mapgen_id` of the nests and each includes their spawn weight in relation to each other. Adding a `null` entry allows for the nest to have a chance to not spawn anything. `Null` also ensures your NPC related nest spawns as a chance instead of being guaranteed. + +**Explicit symbol placement:** + +In the main mapgen's `object` you add the following entry: +Wherever on the main mapgen's `rows` I place a `1` the first set of chunks will spawn. The other set will spawn wherever I place a `2`. The symbol should be placed wherever you want the 0,0 coordinate of your nested map placed. + +``` +"nested": { + "1": { + "chunks": [ [ "null", 60 ], [ "room_10x10_woodworker_E", 30 ], [ "room_10x10_guns_E", 10 ], [ "room_10x10_guns_N", 10 ] ] + }, + "2": { + "chunks": [ + [ "null", 50 ], + [ "room_6x6_brewer_N", 10 ], + [ "room_6x6_junk", 30 ], + [ "room_6x6_office_N", 30 ], + [ "6x6_sewing_open", 20 ], + [ "6x6_electronics_open", 10 ], + [ "room_6x6_brewer_W", 10 ], + [ "room_6x6_junk_W", 30 ], + [ "room_6x6_office_W", 30 ] + ] + } + } +``` + +The main mapgen `rows` with symbols: +``` + "rows": [ + " ", + " ", + " ", + " ", + " |||||||||||||| ", + " |.g...JJJWZ.U| ", + " |F..........<| ", + " |............| ", + " |............| ", + " |......2.....| ", + " |||||||............| ", + " |1.................| ", + " |..................| ", + " |..................| ", + " |..................| ", + " |..........||||||||| ", + " |..........| ", + " |..........| ", + " |..........| ", + " |..........| ", + " |..........| ", + " |||||||||||| ", + " ", + " " + ], +``` + +**Nested maps and z levels:** + +Currently, nested maps do not support z level linking, so any nested map you make will rely on the main mapgen's roof or attempt to generate the c++ roofs. This works with varying degrees of success. Mostly I find it annoying when I can't put a glass roof on greenhouses. + +**Leveraging existing nested maps for modders.** + +As the nested maps used in vanilla increase, modders can make use of these existing entries to incorporate their mod maps into existing buildings. This should greatly expand the mod's ability to add its content into vanilla maps. By using the same `nested mapgen id` and assigning a `weight` to both your new nest and existing nests (as needed). + +I recommend the modder take a look through existing maps and see if there is one that fits the same overall size, orientation, and spawning rarity that they would like their modded nest to have. +You can search for the nested mapgen ids in the github to make sure its representation meets your needs. + + +**Update_mapgen:** + +As mentioned before, Update_mapgen is applied to existing maps due to events that occur during game play. + +Update mapgen will be covered more in advanced guides that address its uses in faction bases and NPC missions. + +For this guide, the most likely use will be for trap triggered update_mapgen. This is a very new feature and currently is used in the microlab and the magiclysm mod's magic basement. + +Since it is still a new feature, it hasn't been expanded upon much. Currently the following limitation applies: +* Traps can only be triggered by a Player or NPC moving on to the trap tile. + +We are going to use the simpler implementation found in the Magiclysm basement over the micro_lab but I'd recommend looking at the micro lab's multi-trap system as well. + +You will need a trap entry (or use an existing one) + +Trap example: +``` + { + "type": "trap", + "id": "tr_magic_door", + "name": "magic door", + "color": "brown", + "symbol": "+", + "visibility": 99, + "avoidance": 99, + "difficulty": 99, + "action": "map_regen", + "map_regen": "magic_door_appear", + "benign": true + } + ``` + + All the trap specific entries can be learned about in other documentation. What concerns us here are the `action` and `map_regen` entries. We want this trap to trigger a `map_regen` action and the `map_regen` references our `update_mapgen_id`. + + update_magen similarities to nested maps: + + * it can target a smaller map chunk. + * it uses the `object` data. + + differences from nested maps: + + * Coordinates used refer to the main mapgen it is updating. + + update_mapgen sample: + + ``` + { + "type": "mapgen", + "update_mapgen_id": "magic_door_appear", + "method": "json", + "object": { + "place_terrain": [ { "ter": "t_carpet_green", "x": 12, "y": 6 } ], + "place_furniture": [ { "furn": "f_beaded_door", "x": 12, "y": 6 } ] + } + } + ``` +In this example, instead of making rows and assigning symbols, I used a condensed alternative with `place_terrain` and `place_furniture`. The x,y coordinates refer to the main mapgen this is altering. This could have used the typical rows coding we normally use in mapgen as well. + +The main mapgen and spawning your trap: + +``` + { + "type": "mapgen", + "method": "json", + "om_terrain": [ "magic_basement" ], + "weight": 100, + "object": { + "fill_ter": "t_carpet_green", + "rows": [ + " ", + " ||||||||||||||| ", + " |gUU|yRRRRRRET| ", + " ||||||~~~%........E| ", + " ||????|||||........L| ", + " ||.......E!|...E....|| ", + " |&.........|.yrrr...<| ", + " ||...$...Py||||||/|||| ", + " ||TIII|||||RRR......| ", + " ||||||88S|.....H..x| ", + " |~~~/.....H..x| ", + " |B~~|.....s..x| ", + " |BYt|RRRR.....| ", + " ||||||||||||||| ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ], + "palettes": [ "standard_domestic_palette" ], + "place_traps": [ { "trap": "tr_magic_door", "x": 21, "y": 4 } ] + } + } + ``` + + I've placed the trap under a coat rack to dissuade casual triggering. Note: when triggered, the trap will update the wall across the room with a beaded door entrance. + + +**Merged maps** + +A merged map is json that has grouped several OMTs together within one mapgen entry. There is no size limit but you should do your best to keep the json readable, so break it up into manageable segments. 3 OMTs together left to right is 72 tiles, and fits easily inside CDDA's preference for no more than 100 columns per line, but some people do as many as 5 OMTs together. More than 5 OMTs together left to right can be hard to read on smaller screens and should be avoided. The same logic applies for vertical grouping: 2-3 OMTs fit easily on most screens, but more than that can be hard to read. + +You can insert existing OMT's into your merged map including forest, field, swamp and water tiles. Generic tiles like forests don't need to be added in your mapgen file, they will be called in the specials.json or multitile_city_buildings entry. + +For the most part, merged maps use the exact same rules and entries as regular mapgen files with a few notable exceptions: + +om_terrain value: + This example is for a map that is 4 OMTs wide and 3 OMTs long (4x3) on the overmap. Each row of OMT's are grouped into an array. + +``` +"om_terrain": [ + [ "farm_stills_4", "farm_stills_3", "farm_stills_2", "farm_stills_1" ], + [ "farm_stills_8", "farm_stills_7", "farm_stills_6", "farm_stills_5" ], + [ "farm_stills_12", "farm_stills_11", "farm_stills_10", "farm_stills_9" ] + ] +``` + +Each OMT's coordinates will continue the row and column numbers, they do not reset to 0,0 at each map boundary. + +For our farm the coordinates will be: +* x sets: + * first OMT: 0,23 + * second OMT: 24,47 + * third OMT: 48,71 + * fourth OMT: 72,95 + +* y sets: + * first row: 0,23 + * second row: 24,47 + * third row: 48,71 + + +The object entries rows reflect all the OMTs together and all the other object entries are shared across all the OMTs: + +``` + "rows": [ + " IFFFFFFFI,,,,IFFFFFFFIffffffffffffffff ,,,, ffffIFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFI ", + " F ,,,, F ???? ???? P,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, , F ", + " F $$$$$$$,,,,$$$$$$$ F -ww- -ww- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F ---..----..--- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, , F ", + " F ,,,, F -x..........x- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ F -....hhhh....w ?,? I ,,,, F ", + " F ,,,, F w....tttt....-????,? F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD,F ", + " F ,,,, F w....tttt....+,,,,,? F , Q ,,,, , , F ", + " F $$$$$$$,,,,$$$$$$$ F w....tttt...Y-?????? F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F -....hhhh....w F, ,,,, , F ", + " F ,,,, F -x..........x- -ww- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ F ----......--------HH---- F , ,,,, F ", + " F ,,,, F -......................- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,,Q F w.;;;;;;;;;;;;;;;;;;;;.w F ,,,, , Q F ", + " F $$$$$$$,,,,$$$$$$$ F -.....................x- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F ---+-----+-----+-----+-- F , , ,,,, , F ", + " F ,,,, F -iiiiu-H...-BB...kk-TiS- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ F -Siiiu-t...-.....h.-iii- F , ,,,, , F ", + " F ,,,, F woiiiu-H...-BB.....-iii- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F -eiiiu-.BB.-.....h.-bbb- F ,,,, , F ", + " F $$$$$$$,,,,$$$$$$$ F -iiiiu-.BBd-BBdddkk-bbb- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F ---+----ww----ww-------- F, , ,,,, ,F ", + " F ,,,, F , F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ Iffff,fffffffffffffffffffffI , ,,,, , F ", + " F ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, , Q F ", + " F $$$$$$$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, , F ", + " F ,,,, I ,, ,,,,,O I DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ F #==#==# ,, ##MMMMM## F Q ,,,, , ,F ", + " F ,,,, F #L_q__# ,, ? #E_____O# F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F #L_q__# ,,, #E______# F ,,,, F ", + " F $$$$$$$,,,,$$$$$$$ F #L____# ,, &#E______W F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F #L_c__# ,,,,,,+_______# F , ,,,, , F ", + " F ,,,, F ####### ,, ?#l______# F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ F ? ,, #l______W F, , ,,,, F ", + " F ,,,, F ,,, #l______# F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F ? ,, #_______# F , ,,,, , , F ", + " F $$$$$$$,,,,$$$$$$$ F ? ,,? ######### F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, F ,, F , ,,,, F ", + " F ,,,, IFFFFFFFFFI,,IFFFFFFFFFFFFFI DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ f ? ,, ? f , , ,,,, , F ", + " F Q ,,,, f 7 7 7,, 7 7 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ? ,, ? f , ,,,, F ", + " F $$$$$$$,,,,$$$$$$$ f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ,, f , ,,,, Q F ", + " F ,,,, f 7 7 7,, 7 7? 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ f ? ,,, ? f, ,,,, , , F ", + " F ,,,, f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ,,, ? f , ,,,, , ,F ", + " F $$$$$$$,,,,$$$$$$$ f 7 7 ,,7 ? 7 7 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f? ? ,, ? f ,,,, F ", + " F ,,,, f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ f ,, ? f , , ,,,, , , F ", + " F ,,,, f 7 7 ,,7 ? 7 7 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ,, ? f , ,,,, F ", + " F $$$$$$$,,,,$$$$$$$ f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ,, ? f, ,,,, , F ", + " F ,,,, f 7 7 ,,7 7 7 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ f ,, ? f , , ,,,, , , F ", + " F ,,,, f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ,, ? f Q ,,,, F ", + " F $$$$$$$,,,,$$$$$$$ f 7 7 ,,7 7 7 7 f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ,,, ? ?f , ,,,, , ,F ", + " F ,,,, Q f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ", + " F $$$$$$$,,,,$$$$$$$ f ? ,,, ? f , , ,,,, F ", + " F ,,,, f 7 7 7,, 7 7 7 f,DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ,,, ? f , , , Q F ", + " F $$$$$$$,,,,$$$$$$$ f ,,,,,,,,,,,,,,,,,,,,,, f DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD F ", + " F ,,,, f ? ,, f , , , F ", + " F f 7 7 7 ? 7 7 7 f DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD F ", + " IFFFFFFFFFFFFFFFFFFFFIFFFFFFFFFFFFFFFFFFFFFFFFFFIFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFI " + ], +``` + +Important note about spawning items, vehicles and monsters: + +While these maps are merged for the benefit of readability, this isn't automatically recognized by our mapgen processes. When you add spawns using x,y coordinates you can't cross OMT boundaries. Make multiple entries if you want those spawns to occur across more than one OMT. This applies for both x and y coordinates. + +An example: each x coordinate encompasses one OMT from a segment of the mall. +``` +"place_monsters": [ + { "monster": "GROUP_MALL", "x": [ 2, 23 ], "y": [ 2, 23 ], "density": 0.15 }, + { "monster": "GROUP_MALL", "x": [ 26, 47 ], "y": [ 2, 23 ], "density": 0.3 }, + { "monster": "GROUP_MALL", "x": [ 49, 71 ], "y": [ 2, 10 ], "density": 0.2 }, + { "monster": "GROUP_MALL", "x": [ 56, 68 ], "y": [ 17, 21 ], "density": 0.1 }, + { "monster": "GROUP_MALL", "x": [ 73, 95 ], "y": [ 2, 10 ], "density": 0.2 }, + { "monster": "GROUP_MALL", "x": [ 73, 95 ], "y": [ 17, 19 ], "density": 0.1 }, + { "monster": "GROUP_MALL", "x": [ 98, 119 ], "y": [ 0, 11 ], "density": 0.2 }, + { "monster": "GROUP_MALL", "x": [ 96, 105 ], "y": [ 16, 21 ], "density": 0.1 }, + { "monster": "GROUP_MALL", "x": [ 170, 191 ], "y": [ 2, 23 ], "density": 0.1 }, + { "monster": "GROUP_MALL", "x": [ 194, 215 ], "y": [ 2, 23 ], "density": 0.05 } + ] +``` + +* You can mostly get around this by using explicit symbol placement instead, which will apply to all the OMT's within your `rows`. This can get a little messy for monster and vehicle spawns, so I usually keep those to x,y coordinates. + +* Vehicles that spawn across 2 OMT's won't spawn at all. So if you can't get your vehicle to spawn, adjust its placement. Vehicle's 0,0 coordinate can vary depending on the vehicle's own json entry so this usually will take some trial and error to get them spawning nicely. + +* Nested maps of all sorts can be used in a merged map, but they can't cross boundary lines (the nested map will be cut off at the boundary). + +* More information about monster spawning can be found in [doc/MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md#spawn-item-or-monster-groups-with-place_groups) + +Note: set point type entries (see the example below) don't work well with merged maps and the issue has been reported. If you use this entry, the points will be repeated in every OMT in your merged map. + +sample: +``` +"set": [ + { "point": "trap", "id": "tr_funnel", "x": [ 2, 9 ], "y": 19, "repeat": [ 1, 2 ] }, + { "point": "trap", "id": "tr_cot", "x": [ 2, 9 ], "y": [ 15, 17 ], "repeat": [ 1, 2 ] } + ] +``` +I wanted to place this cot and funnel in the first OMT but it is repeated every time it encounters a new OMT boundary. From 76cbb72ffbd63744c43d40b76910c292b9028c10 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Tue, 30 Jun 2020 00:06:03 -0700 Subject: [PATCH 30/41] Restructure NPC chit-chat to include lore, and be generally more flexible (#41668) --- data/json/npcs/TALK_FRIEND_CONVERSATION.json | 105 +++++++++++------ data/json/npcs/talk_tags.json | 34 ------ data/json/npcs/talk_tags_chat.json | 118 +++++++++++++++++++ 3 files changed, 188 insertions(+), 69 deletions(-) create mode 100644 data/json/npcs/talk_tags_chat.json diff --git a/data/json/npcs/TALK_FRIEND_CONVERSATION.json b/data/json/npcs/TALK_FRIEND_CONVERSATION.json index 0d25832db6c5b..78ee3d0a6ffe4 100644 --- a/data/json/npcs/TALK_FRIEND_CONVERSATION.json +++ b/data/json/npcs/TALK_FRIEND_CONVERSATION.json @@ -33,46 +33,81 @@ "id": "TALK_FRIEND_CHAT", "type": "talk_topic", "dynamic_line": [ - { "u_has_item": "beer", "yes": "", "no": "" }, - { "u_has_item": "european_pilsner", "yes": "", "no": "" }, - { "u_has_item": "pale_ale", "yes": "", "no": "" }, - { "u_has_item": "india_pale_ale", "yes": "", "no": "" }, - { "u_has_item": "wine_barley", "yes": "", "no": "" }, { - "is_season": "summer", - "yes": "Yeah, this summer heat is hitting me hard, let's take a quick break, how goes it ?", - "no": "" - }, - { - "is_season": "winter", - "yes": "OK, maybe it'll stop me from freezing in this weather, what's up?", - "no": "" - }, - { - "is_day": "Well, it's the time of day for a quick break surely! How are you holding up?", - "no": "Man it's dark out isn't it? What's up?" - }, - { - "npc_has_effect": "infected", - "yes": "Well, I'm feeling pretty sick… are you doing OK though?", - "no": "" - }, - { - "has_no_assigned_mission": "", - "no": { - "has_many_assigned_missions": "Definitely, by the way, thanks for helping me so much with my tasks! Anyway, you coping OK, ? ", - "no": "OK, let's take a moment, oh, and thanks for helping me with that thing, so… what's up?" - } - }, - { - "days_since_cataclysm": 30, - "yes": "Now, we've got a moment, I was just thinking it's been a month or so since… since all this, how are you coping with it all?", - "no": "" + "days_since_cataclysm": 100, + "yes": [ + { "u_has_item": "beer", "yes": " ", "no": "" }, + { + "u_has_item": "european_pilsner", + "yes": " ", + "no": "" + }, + { + "u_has_item": "pale_ale", + "yes": " ", + "no": "" + }, + { + "u_has_item": "india_pale_ale", + "yes": " ", + "no": "" + }, + { + "u_has_item": "wine_barley", + "yes": " ", + "no": "" + }, + { + "is_season": "summer", + "yes": " ", + "no": "" + }, + { + "is_season": "winter", + "yes": " ", + "no": "" + }, + { + "npc_has_effect": "infected", + "yes": " ", + "no": "" + }, + { "npc_has_intelligence": 8, "yes": "", "no": "" }, + { "npc_has_perception": 8, "yes": "", "no": "" } + ], + "no": [ + { "u_has_item": "beer", "yes": " ", "no": "" }, + { + "u_has_item": "european_pilsner", + "yes": " ", + "no": "" + }, + { "u_has_item": "pale_ale", "yes": " ", "no": "" }, + { + "u_has_item": "india_pale_ale", + "yes": " ", + "no": "" + }, + { + "u_has_item": "wine_barley", + "yes": " ", + "no": "" + }, + { "is_season": "summer", "yes": " ", "no": "" }, + { "is_season": "winter", "yes": " ", "no": "" }, + { + "npc_has_effect": "infected", + "yes": " ", + "no": "" + }, + { "npc_has_intelligence": 8, "yes": "", "no": "" }, + { "npc_has_perception": 8, "yes": "", "no": "" } + ] } ], "responses": [ { - "text": "Oh you know, not bad, not bad…", + "text": "", "topic": "TALK_DONE", "switch": true, "effect": [ "morale_chat_activity", { "npc_add_effect": "asked_to_socialize", "duration": 7000 } ] diff --git a/data/json/npcs/talk_tags.json b/data/json/npcs/talk_tags.json index c0c5dea450a1d..6f8b7f3142d7c 100644 --- a/data/json/npcs/talk_tags.json +++ b/data/json/npcs/talk_tags.json @@ -148,40 +148,6 @@ "I'd kill for a sip of water right now." ] }, - { - "type": "snippet", - "category": "", - "//": "Used when chit-chatting while the avatar has a beer", - "text": [ - "Yeah sure, can't help but notice you got beer with you! Let's crack a cold one and chat, , how goes it?", - "Oh definitely, how about one of those beers I see on you? What's up anyway?", - "Yeah you share those beers I see you hoarding and then we chat all you like! Only joking, what's up ?", - "Hey , I bet a chat would be all the sweeter with a nice, cold beer in hand. How's it going?", - "While we chat, what say you we open a beer and just… pretend the world isn't ending, just for a while?", - "Pass me one and let's talk about the good ol' days, ." - ] - }, - { - "type": "snippet", - "category": "", - "//": "General chit chat messages", - "text": [ - "Hey, sure thing, , I need a break anyway, how are you?", - "Yeah OK, , how's it going?", - "Sure, let's shoot the shit! You OK?", - "Why not? How you doing?", - "I'm OK with that, what's up?", - "I can spare a few minutes, how's things?", - "Sure thing , you good?", - "Alright, you got something to get off your chest?", - "Always ready for a good chat! But why, you OK?", - "OK , we should get to know each other, how are you coping?", - "Definitely, I'm game. How you holding up?", - "Good idea . Let's forget the world for a while. How you doin'?", - "Ah, what the heck. How's life been treating you?", - "Sure. So, how about that weather ey?" - ] - }, { "type": "snippet", "category": "", diff --git a/data/json/npcs/talk_tags_chat.json b/data/json/npcs/talk_tags_chat.json new file mode 100644 index 0000000000000..55a9b672fd038 --- /dev/null +++ b/data/json/npcs/talk_tags_chat.json @@ -0,0 +1,118 @@ +[ + { + "type": "snippet", + "category": "", + "//": "Used when chit-chatting while the avatar has a beer; goes before a general chitchat message", + "text": [ + "Yeah sure, want to crack open one of them beers?", + "Oh definitely, how about one of those beers you got?", + "Yeah you share those beers I see you hoarding and then we chat all you like! Only joking, heh.", + "Hey , I bet a chat would be all the sweeter with a nice, cold beer in hand.", + "While we chat, what say you we open a beer and just… pretend the world isn't ending.", + "Pass me one and let's talk, ." + ] + }, + { + "type": "snippet", + "category": "", + "//": "A sentence regarding the season to go before a more general chitchat message.", + "text": [ + "Yeah, this summer heat is hitting me hard, you know?", + "Enjoying the summer.", + "Kinda wishing it would cool off a bit, to be honest." + ] + }, + { + "type": "snippet", + "category": "", + "//": "A sentence regarding the season to go before a more general chitchat message.", + "text": [ + "OK, maybe it'll stop me from freezing in this weather.", + "Gotta say, I'm not minding the snow.", + "It's weird the zombies don't freeze." + ] + }, + { + "type": "snippet", + "category": "", + "//": "A sentence about being sick to go before a more general chitchat message.", + "text": [ "Well, I'm feeling pretty sick… but sure." ] + }, + { + "type": "snippet", + "category": "", + "//": "General chit chat messages", + "text": [ + "", + "I need a break anyway, how are you?", + "So, how's it going?", + "Let's shoot the shit! You OK, ?", + "I'm OK with that, what's up?", + "I guess I can spare a few minutes, how's things?", + "Sure thing , you good?", + "Alright, you got something to get off your chest?", + "Always ready for a good chat! But why, you OK?", + "OK , how are you coping?", + "I'm game. How you holding up?", + "Let's forget the world for a while. How you doin'?", + "What the heck. How's life been treating you?", + "So, how about that weather, eh?", + "Nice of you to make time. How's it been for you lately?", + "My dogs’ve been barkin’ lately, you know?", + "I feel great today. Not sure what it is, just one of those days." + ] + }, + { + "type": "snippet", + "category": "", + "//": "General chit chat messages for NPCs having big thoughts. Tends to be more about establishing game lore.", + "text": [ + "I just can't believe it's over. I keep running my head back to the days it all fell apart. The riots. The lies. The psychos. It never really felt like it was going to go like this.", + "You ever think there's any truth to the crap they were spouting before the world ended? Mind control drugs in the water, bio-terrorism? Some of it would make sense, but it seems so far-fetched. Then again, we're dealing with actual zombies.", + "I wonder if I should be getting more religious now, or less. You know what I'm sayin', ?", + "I been thinkin’ about rearranging my gear. It’s a real mess. Don’t wanna go for my weapon and accidentally pull out a granola bar, right?", + "You ever wonder why we even bother? We’re all just gonna be zombies eventually anyway. I mean, not that I’m gonna stop fighting, but what’s the damn point?", + "I wish I could go bust a cap in one of those zombies right now, without all the fuss about being scared for my life.", + "Every time I close my eyes, I can still see the riots. Do you get that, or is it just me?", + "You ever feel like the whole time before the apocalypse was just a dream you’re waking up from?", + "When do you think you realized the world was ending? For me, it was that damned YouTube video with the lady killing the baby. Holy shit, you know?", + "I wonder if the government's still out there, holed up in some bunker.", + "Remember some of the crazy news from the end of the world? The stuff that got drowned out by the riot coverage I mean. Like, didn't the governor of Rhode Island secede from the Union or something?", + "I keep having dreams that zombies still remember who they were as people, and are just trapped inside the bodies watching everything happen. Haven't been sleeping well.", + "Those mind-control drugs they put in the water to make people riot… you think they're still in there?" + ] + }, + { + "type": "snippet", + "category": "", + "//": "General chit chat messages for intelligent or perceptive NPCs", + "text": [ + "I can't stop wondering who fucked up to make all this happen. Obviously we can't trust the news, they claimed the zombies were \"rioters\" for weeks. Why? Where did this come from?", + "If what they told us about the Chinese was even partly true, do you think it's like this in China? Or maybe the US is some kind of quarantine zone, and at least some of the world is still out there.", + "Have you noticed injuries aren’t healing the same as usual? I started spotting it before the world ended, but it’s become more pronounced. There’s hardly even a granulation step after a cut closes.", + "I still don’t understand how these zombies are powered. They’re like perpetual motion machines.", + "So many parts of this still don't fit together. Who created the zombies? What powers them? Maybe the rumours of mind control drugs were true all along, and someone found a way to bioengineer living dead." + ] + }, + { + "type": "snippet", + "category": "", + "//": "General chit chat messages for further past the apocalypse", + "text": [ + "", + "", + "How do these zombies even keep going? What are they eating? Do you think they'll ever rot away?", + "I been thinkin', one of these days, we're gonna run out of toilet paper. What then?", + "Do you think it’s weird how we’ll, like, open a locked building and find a lone zombie inside? How’d it even get there?", + "Sometimes I wonder if we're all psychos, not just the ones that went crazy and rioted. I never would have thought I could do the things I've done since the world ended.", + "You read any good books lately? I'm glad we still got books.", + "You know what I miss? Movie theaters. You think Hollywood survived this? Maybe there's a bunch of zombie actors out there, filmin' shit out of reflex. Hah, I'd watch that shit." + ] + }, + { + "type": "snippet", + "category": "", + "//": "General chit chat responses from the player", + "text": [ "I hear you, …", "That reminds me of something…", "Right, right. Say, you ever thought about…" ] + } +] From 96bd322737e521bcb1159b4ab8762c8d9a9cfed6 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Tue, 30 Jun 2020 00:06:38 -0700 Subject: [PATCH 31/41] Create "cataclysm: what happened" stories, part 1 (#41672) --- data/json/npcs/BG_trait_groups.json | 4 + data/json/npcs/BG_traits.json | 50 +++++--- .../backgrounds_table_of_contents.json | 6 + data/json/npcs/Backgrounds/confused_1.json | 18 +++ data/json/npcs/Backgrounds/dreamer.json | 18 ++- data/json/npcs/Backgrounds/evacuee_1.json | 6 + data/json/npcs/Backgrounds/evacuee_2.json | 6 + data/json/npcs/Backgrounds/evacuee_3.json | 16 ++- data/json/npcs/Backgrounds/evacuee_4.json | 26 ++++ data/json/npcs/Backgrounds/evacuee_5.json | 18 ++- data/json/npcs/Backgrounds/evacuee_6.json | 8 +- .../json/npcs/Backgrounds/fema_evacuee_1.json | 26 ++++ .../npcs/Backgrounds/left_for_dead_1.json | 33 +++++- .../npcs/Backgrounds/left_for_dead_2.json | 16 +++ .../npcs/Backgrounds/left_for_dead_3.json | 74 ++++++++++++ data/json/npcs/Backgrounds/no_past_1.json | 15 +++ data/json/npcs/Backgrounds/no_past_2.json | 8 +- data/json/npcs/Backgrounds/no_past_4.json | 39 ++++++ data/json/npcs/Backgrounds/religious_1.json | 16 +++ data/json/npcs/Backgrounds/religious_2.json | 6 + data/json/npcs/Backgrounds/wedding_1.json | 7 ++ .../whathappened_table_of_contents.json | 111 ++++++++++++++++++ data/json/npcs/talk_tags.json | 10 ++ 23 files changed, 511 insertions(+), 26 deletions(-) create mode 100644 data/json/npcs/Backgrounds/left_for_dead_3.json create mode 100644 data/json/npcs/Backgrounds/whathappened_table_of_contents.json diff --git a/data/json/npcs/BG_trait_groups.json b/data/json/npcs/BG_trait_groups.json index 31dce06070678..deb5e4b7bc326 100644 --- a/data/json/npcs/BG_trait_groups.json +++ b/data/json/npcs/BG_trait_groups.json @@ -33,6 +33,7 @@ { "trait": "BGSS_FEMA_Evacuee_1" }, { "trait": "BGSS_Left_for_Dead_1" }, { "trait": "BGSS_Left_for_Dead_2" }, + { "trait": "BGSS_Left_for_Dead_3" }, { "trait": "BGSS_Gung_Ho_1" }, { "trait": "BGSS_Gung_Ho_2" }, { "trait": "BGSS_Gung_Ho_3" }, @@ -72,6 +73,7 @@ "subtype": "distribution", "traits": [ { "group": "BG_survival_story_UNIVERSAL" }, + { "trait": "BGSS_Left_for_Dead_3" }, { "trait": "BGSS_Hospital_1" }, { "trait": "BGSS_Hospital_2" }, { "trait": "BGSS_Hospital_3" } @@ -84,6 +86,7 @@ "subtype": "distribution", "traits": [ { "group": "BG_survival_story_UNIVERSAL" }, + { "trait": "BGSS_Left_for_Dead_3" }, { "trait": "BGSS_Gung_Ho_1" }, { "trait": "BGSS_Gung_Ho_2" }, { "trait": "BGSS_Gung_Ho_3" }, @@ -126,6 +129,7 @@ { "trait": "BGSS_Evacuee_4" }, { "trait": "BGSS_Evacuee_5" }, { "trait": "BGSS_Evacuee_6" }, + { "trait": "BGSS_Left_for_Dead_3" }, { "trait": "BGSS_High_School_1" }, { "trait": "BGSS_Burger_Flipper_1" }, { "trait": "BGSS_Nerd_1" } diff --git a/data/json/npcs/BG_traits.json b/data/json/npcs/BG_traits.json index e3ac16db4d155..a3921ba400172 100644 --- a/data/json/npcs/BG_traits.json +++ b/data/json/npcs/BG_traits.json @@ -6,7 +6,7 @@ { "type": "mutation", "id": "BGSS_Confused_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Confused 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -18,7 +18,7 @@ { "type": "mutation", "id": "BGSS_No_Past_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: No Past 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -30,7 +30,7 @@ { "type": "mutation", "id": "BGSS_No_Past_2", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: No Past 2" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -42,7 +42,7 @@ { "type": "mutation", "id": "BGSS_No_Past_3", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: No Past 3" }, "player_display": false, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", @@ -54,7 +54,7 @@ { "type": "mutation", "id": "BGSS_No_Past_4", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: No Past 4" }, "player_display": false, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", @@ -66,7 +66,7 @@ { "type": "mutation", "id": "BGSS_No_Past_5", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: No Past 5" }, "player_display": false, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", @@ -78,7 +78,7 @@ { "type": "mutation", "id": "BGSS_Religious_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Religious 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -90,7 +90,7 @@ { "type": "mutation", "id": "BGSS_Religious_2", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Religious 2" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -102,7 +102,7 @@ { "type": "mutation", "id": "BGSS_Dreamer", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Dreamer 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -114,7 +114,7 @@ { "type": "mutation", "id": "BGSS_Wedding_1", - "name": { "str": "Survivor" }, + "name": { "str": "Survivor: Wedding 1" }, "player_display": false, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", @@ -126,7 +126,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -138,7 +138,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_2", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 2" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -150,7 +150,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_3", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 3" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "valid": false, @@ -161,7 +161,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_4", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 4" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -173,7 +173,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_5", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 5" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -185,7 +185,7 @@ { "type": "mutation", "id": "BGSS_Evacuee_6", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Evacuee 6" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -197,7 +197,7 @@ { "type": "mutation", "id": "BGSS_FEMA_Evacuee_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: FEMA Evacuee 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -209,7 +209,7 @@ { "type": "mutation", "id": "BGSS_Left_for_Dead_1", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Left for Dead 1" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, @@ -221,7 +221,19 @@ { "type": "mutation", "id": "BGSS_Left_for_Dead_2", - "name": { "str": "Survivor Story" }, + "name": { "str": "Survivor: Left for Dead 2" }, + "points": 0, + "description": "This NPC could tell you about how they survived the Cataclysm", + "player_display": false, + "valid": false, + "purifiable": false, + "types": [ "BACKGROUND_SURVIVAL_STORY" ], + "flags": [ "BG_SURVIVAL_STORY" ] + }, + { + "type": "mutation", + "id": "BGSS_Left_for_Dead_3", + "name": { "str": "Survivor: Left for Dead 3" }, "points": 0, "description": "This NPC could tell you about how they survived the Cataclysm", "player_display": false, diff --git a/data/json/npcs/Backgrounds/backgrounds_table_of_contents.json b/data/json/npcs/Backgrounds/backgrounds_table_of_contents.json index ac968970c8f30..59ada7fac0628 100644 --- a/data/json/npcs/Backgrounds/backgrounds_table_of_contents.json +++ b/data/json/npcs/Backgrounds/backgrounds_table_of_contents.json @@ -117,6 +117,12 @@ "condition": { "npc_has_trait": "BGSS_Left_for_Dead_2" }, "switch": true }, + { + "text": "", + "topic": "BGSS_LEFT_FOR_DEAD_3_STORY1", + "condition": { "npc_has_trait": "BGSS_Left_for_Dead_3" }, + "switch": true + }, { "text": "", "topic": "BGSS_GUNG_HO_1_STORY1", diff --git a/data/json/npcs/Backgrounds/confused_1.json b/data/json/npcs/Backgrounds/confused_1.json index 788f7d90b15e4..a94446af96052 100644 --- a/data/json/npcs/Backgrounds/confused_1.json +++ b/data/json/npcs/Backgrounds/confused_1.json @@ -4,5 +4,23 @@ "type": "talk_topic", "dynamic_line": "I don't even know anymore. I have no idea what is going on. I'm just doing what I can to stay alive. The world ended and I bungled along not dying, until I met you.", "responses": [ { "text": "Huh.", "topic": "TALK_FRIEND" } ] + }, + { + "id": "CWH_CONFUSED_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "I barely understand what's going on *now*. Why do you think I'd know how the world ended?", + "responses": [ + { + "text": "OK, fine. Can you at least tell me what you remember about the events leading up to now?", + "topic": "CWH_CONFUSED_1_IDEAS2" + }, + { "text": "Never mind then.", "topic": "TALK_FRIEND" } + ] + }, + { + "id": "CWH_CONFUSED_1_IDEAS2", + "type": "talk_topic", + "dynamic_line": "What, don't you remember? No, sorry, that's not fair, it was a weird time. OK, well, I guess this all started with the riots, didn't it? We were just leading our lives, doing our jobs, and then people started rioting. Not the usual protests that turned violent or anything, either, people just left their houses and started breaking shit. The news tried to downplay it but they couldn't keep it off the internet. I don't know what caused it, they said it was some kind of drug or toxin in the water? Still, I didn't really realize how bad it was getting at first. Somewhere along the way the \"rioters\" started getting up and walking around with holes in their chests, and that's when the real panic took over. The next few days - or weeks, not really sure - are a blur to me. You'd have to ask someone else how we got from there to total collapse.", + "responses": [ { "text": "Thanks for filling me in.", "topic": "TALK_FRIEND" } ] } ] diff --git a/data/json/npcs/Backgrounds/dreamer.json b/data/json/npcs/Backgrounds/dreamer.json index 76fcd39c2c7ac..610b694525749 100644 --- a/data/json/npcs/Backgrounds/dreamer.json +++ b/data/json/npcs/Backgrounds/dreamer.json @@ -5,7 +5,7 @@ "dynamic_line": "OK, this is gonna sound crazy but I, like, I knew this was going to happen. Like, before it did. You can even ask my psychic except, like, I think she's dead now. I told her about my dreams a week before the world ended. Serious!", "responses": [ { "text": "What were your dreams?", "topic": "BGSS_DREAMER_STORY2" }, - { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] }, @@ -68,5 +68,21 @@ { "text": "Poor Filthy Dan. ", "topic": "TALK_FRIEND" }, { "text": "Thanks for telling me that stuff. ", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_DREAMER_IDEAS1", + "type": "talk_topic", + "dynamic_line": "So, like, there were some really bad riots, okay? Everyone got realy violent and nasty, and to be honest, I was on a bit of a spirit journey for a lot of it and I don't really remember too well. But the weirdest part is, nobody even *cared* about each other. It's like all our caring got sucked away. I think it was some kind of negative energy thing. And also that made the dead, like, come back to life and stuff. Plus, like, there were some monsters? I'm not really sure how they fit in.", + "responses": [ + { "text": "You seem to know a lot, what do you think caused it all?", "topic": "CWH_DREAMER_IDEAS2" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_DREAMER_IDEAS2", + "type": "talk_topic", + "dynamic_line": "That's a tough one, but I keep thinking back to this dream I had like, a year before it all started. I dreamed there was this big ball of evil energy that was just waiting to suck up all the good thoughts on the earth and turn us into monsters and things? So I guess that's what I think happened. Everything else just seems too far-fetched, you know?", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_1.json b/data/json/npcs/Backgrounds/evacuee_1.json index a645900ebbce1..e449a5a05fbf3 100644 --- a/data/json/npcs/Backgrounds/evacuee_1.json +++ b/data/json/npcs/Backgrounds/evacuee_1.json @@ -54,5 +54,11 @@ "type": "talk_topic", "dynamic_line": "I thought I had those damned figured out. I got braver, started heading out by day more and more. One of those screamer zombies spotted me and called in a horde, with a giant beastie at the head of it, the size of a volkswagen and all covered in bone plates. I know when I'm outclassed. The big guy was held back by his own horde of buddies, and I managed to book it back to my place. I closed the windows, locked it down, but it was too late. The giant followed me and just started hammering right through the walls. I grabbed what I could and made for the horizon. Last I saw of my squat, it was collapsing on the bastard. For all I know, it died in the crash, but I am not going back to find out.", "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "What happened? I'm not really sure. You must know about the riots and all that, that the government and the police totally failed to contain. I don't have a good guess what caused that. I thought it was the usual stuff at first, and I gotta admit, I was sort of excited and scared it was the start of a revolution. Not excited enough to join in though, and I guess anyone who was is probably dead now. I tried to wait it out at home, packed a little bug-out bag, but then the internet started showing videos of rioters getting back up and fighting with crazy injuries. I don't know how many people really believed it at first, but I took that as my sign and ditched town for the evac shelter. I don't know exactly what happened after that. The center I was in was heavily vandalized and empty, and I never saw anyone else. The cell phone grid was locked up, except for one emergency message that came through around a day later saying the government had fallen. Power went out a few days later.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_2.json b/data/json/npcs/Backgrounds/evacuee_2.json index 806fef3d56d82..2dc69e2e061ec 100644 --- a/data/json/npcs/Backgrounds/evacuee_2.json +++ b/data/json/npcs/Backgrounds/evacuee_2.json @@ -27,5 +27,11 @@ "dynamic_line": "What do you think happened? You see them around anywhere?", "speaker_effect": [ { "effect": { "npc_add_effect": "player_BGSS_SAIDNO", "duration": "14000" } } ], "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_2_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Well, I assume you know about the riots and the military and police and the freakin' nightmare monsters walking the earth beside zombies, right? If you're asking what I think caused it all, well, I dunno. My best guess it was some huge government overreach, maybe some kind of experimental bioweapon that got away. They tried to lie so much at the start about everything that was going on, I don't think the whole 'Chinese attack' shit measures up. They were trying to cover something up. As for the real end times, maybe the rest of the world tried to contain it. I heard there were honest-to-god nukes going off here on American soil. To me that seems like somewhere else, maybe Europe, trying to get whatever is going on here contained. Maybe it even worked. It's bad now but it's not like it was.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_3.json b/data/json/npcs/Backgrounds/evacuee_3.json index 7a855cb2f739d..f753a6fdd053b 100644 --- a/data/json/npcs/Backgrounds/evacuee_3.json +++ b/data/json/npcs/Backgrounds/evacuee_3.json @@ -64,10 +64,22 @@ "id": "BGSS_EVACUEE_3_STORY4", "type": "talk_topic", "dynamic_line": "Yeah. I had it pretty good there, but eventually I just started going a bit nuts. Always dark, a bit cold, living off scavenged junk food… a soul can only live like that for so long. When the weather above ground got warmer and the daylight hours got longer I decided to get a bit braver. I'd learned enough about the that I was able to live pretty well after that. I've camped a few places, scavenged berries and whatnot, lived a pretty good life compared to those first few months.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_3_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Woah, , I don't even know where to start. The riots? I think it was going on sooner than that. There were bad murmurs going on a few weeks before that happened. Lots of really scary crimes, not your usual stuff but like cannibalism and some real unspeakable shit, you know? When the riots started, I think I was already primed to think of it as something different from a normal equality riot or anything like that. I think that's part of how I got out safer, I had had some time to get some stuff and get going, and didn't try to make shopping trips. People were abso-fuckin-lutely crazy in those days. It was a lot like the pandemic a few years back, except the police were out in the streets in force, gunning people down like it was going out of style.", "responses": [ - { "text": "I didn't meet you in the subway though. You left.", "topic": "BGSS_EVACUEE_3_STORY4" }, - { "text": "", "topic": "TALK_FRIEND" }, + { "text": "Do you have any idea what the actual cause was?", "topic": "CWH_EVACUEE_3_IDEAS2" }, + { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_3_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Not really. Government fed us all kinds of conflicting stories, and there was some absolutely heinous stuff going on. I mean, you can't have missed that video of the woman killing her own baby, right? God, that still gives me nightmares. I don't know what it was about it, something about the look on her face. Worse stuff came out of course, and now we've both seen worse things with our own eyes, but that one still comes back to haunt me. Anyway, they never could control the riots, and by the time the rioters started turning into undead it was way too late. I don't know if morale just broke or what but I heard rumours the military and police started turning on each other as much as the crowds. What actually made the dead come back to life though? I haven't got a clue.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_4.json b/data/json/npcs/Backgrounds/evacuee_4.json index 6552689ebf4e8..d3c04bfc340a5 100644 --- a/data/json/npcs/Backgrounds/evacuee_4.json +++ b/data/json/npcs/Backgrounds/evacuee_4.json @@ -3,6 +3,32 @@ "id": "BGSS_EVACUEE_4_STORY1", "type": "talk_topic", "dynamic_line": "They were shipping me with a bunch of evacuees over to a refugee center, when the bus got smashed in by the biggest zombie you ever saw. It was busy with the other passengers, so I did what anyone would do and fucked right out of there.", + "responses": [ + { "text": "Don't leave me hanging, what happened next?", "topic": "BGSS_EVACUEE_4_STORY2" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_EVACUEE_4_STORY2", + "type": "talk_topic", + "dynamic_line": "I ran until I felt like my lungs were going to jump right out of my mouth. I holed up in the forest for the night, under a fir tree. In the morning I heard someone talking, so I went to see. I was playing it pretty careful though, there were still a lot of psychos and rioters around. I snuck up on some kind of thing, some monster worse than any zombie. Some huge bug thing, saying random phrases like some kind of broken tape recorder. It was dragging a few human bodies behind it, I couldn't tell if they were dead or unconscious. Honestly I didn't wait to find out, I ducked into the bushes and tried not to breath until I couldn't hear it anymore.", + "responses": [ + { "text": "Where did you go from there?", "topic": "BGSS_EVACUEE_4_STORY3" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_EVACUEE_4_STORY3", + "type": "talk_topic", + "dynamic_line": "Once I was okay leaving the bushes, I made my way to an old shed I could see a ways off. It was falling in but it kept the rain and wind off and gave me a place out of sight. I stayed there until I ran out of those ass-tasting ration bars I'd filled my backpack with. Then I took on the wanderin' life until we met.", "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_4_IDEAS1", + "type": "talk_topic", + "dynamic_line": "What's this, some kinda Back to the Future thing? How could you not know what happened? The world damn well ended, that's what. And it didn't start with an earthquake, birds, snakes, or aeroplanes. It started with riots, and they had to dispatch cops and then the military to take care of the criminals. The government tried to pad it claiming it was some kind of mind control, but I didn't see too much different from the usual bullshit: entitled babies looking for an excuse to break the law. It just got way worse, this time, until it was time to get out of dodge. I heard rumours they were even bombing some of the urban centers to try to control it - which, I have to admit, is maybe a bit too hard-core.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_5.json b/data/json/npcs/Backgrounds/evacuee_5.json index 67f7866f4ed82..5891624f6c4b8 100644 --- a/data/json/npcs/Backgrounds/evacuee_5.json +++ b/data/json/npcs/Backgrounds/evacuee_5.json @@ -25,7 +25,7 @@ "topic": "BGSS_EVACUEE_5_WASPS", "condition": { "u_has_perception": 8 } }, - { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] }, @@ -37,5 +37,21 @@ { "text": "Sorry. Could you tell me more about them?", "topic": "BGSS_EVACUEE_5_BEES" }, { "text": "Right. Sorry.", "topic": "TALK_FRIEND" } ] + }, + { + "id": "CWH_EVACUEE_5_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Okay listen. Don't believe that government stuff. There's a common thread to all of it: the riots, the military failing to contain it, even the giant monsters they said were appearing in the last few days and had to be wiped out with nukes.", + "responses": [ + { "text": "You've got my attention.", "topic": "CWH_EVACUEE_5_IDEAS2" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_EVACUEE_5_IDEAS1", + "type": "talk_topic", + "dynamic_line": "You ever see the Matrix? This is it. In real life. To keep us locked in here, the creators of the simulation have to make sure we're just the right level of miserable. I think their algorithms got messed up though, and went into overdrive, because all this is a little implausible. Still, I guess we're still jacked in, so maybe it's working.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/evacuee_6.json b/data/json/npcs/Backgrounds/evacuee_6.json index 252ff39d42f61..b447e06fc22fe 100644 --- a/data/json/npcs/Backgrounds/evacuee_6.json +++ b/data/json/npcs/Backgrounds/evacuee_6.json @@ -3,6 +3,12 @@ "id": "BGSS_EVACUEE_6_STORY1", "type": "talk_topic", "dynamic_line": "Well, I was at home when the cell phone alert went off and told me to get to an evac shelter. So I went to an evac shelter. And then the shelter got too crowded, and people were waiting to get taken to the refugee center, but the buses never came. You must already know about all that. It turned into panic, and then fighting. I didn't stick around to see what happened next; I headed into the woods with what tools I could snatch from the lockers. I went back a few days later, but the place was totally abandoned. No idea what happened to all those people.", - "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_EVACUEE_6_IDEAS1", + "type": "talk_topic", + "dynamic_line": "I gotta be honest with you, I heard a lot of stories back at the shelter, and only one of them really stuck. This is some kind of science experiment gone wrong. I don't know what caused the riots and the undead in the first place, but there's no way it's this out of control everywhere. Yeah, I got the same 'the government has fallen' text as everyone, but it doesn't make *sense* that it could be so widespread so fast. I think we're in some sort of exclusion zone, where they're letting whatever is going on run its course to see how it works so they can fight it better next time. Somewhere out there, outside the zone, it's more or less business as usual.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/fema_evacuee_1.json b/data/json/npcs/Backgrounds/fema_evacuee_1.json index ad01bae9c82e4..03963ba1ca279 100644 --- a/data/json/npcs/Backgrounds/fema_evacuee_1.json +++ b/data/json/npcs/Backgrounds/fema_evacuee_1.json @@ -81,5 +81,31 @@ "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_FEMA_EVACUEE_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Woof, you ready for a real hot take? The government did this to us. Intentionally, or at least sort-of intentionally.", + "responses": [ + { "text": "Oh?", "topic": "CWH_FEMA_EVACUEE_1_IDEAS2" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_FEMA_EVACUEE_1_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Damn right. They lied to us for god knows how long about what was going on because they didn't want us to figure it out. It probably started as a way to keep the people in line, but it backfired somehow. My guess is they tried to de-educate us, tried to mislead us, and when that wasn't working they tried actual drugs in the water to make us stupid or something. Instead of just stupid, some people got violent. Then they tried to leverage that to put in martial law, but that didn't work and they wound up fighting hordes of people. Only they didn't realize their brain drugs were some kind of mutagen that turn people into zombies.", + "responses": [ + { "text": "What about all the other stuff?", "topic": "CWH_FEMA_EVACUEE_1_IDEAS3" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_FEMA_EVACUEE_1_IDEAS3", + "type": "talk_topic", + "dynamic_line": "I think it's mostly mutation. I don't know what they used, but it's some real mad science shit, I didn't think most of this was even possible. I also wonder if whatever they put in the water has made us a bit crazy. Maybe some of this is just a hallucination? That one blows my mind a bit, I'm not sure I believe it but I got nothin' else.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/left_for_dead_1.json b/data/json/npcs/Backgrounds/left_for_dead_1.json index c9649b57f09fd..e8b32a4800a04 100644 --- a/data/json/npcs/Backgrounds/left_for_dead_1.json +++ b/data/json/npcs/Backgrounds/left_for_dead_1.json @@ -3,6 +3,37 @@ "id": "BGSS_LEFT_FOR_DEAD_1_STORY1", "type": "talk_topic", "dynamic_line": "I was late to evacuate when the shit hit the fan. Got stuck in town for a few days, survived by hiding in basements eating girl scout cookies and drinking warm root beer. Eventually I managed to weasel my way out without getting caught by the . I spent a few days holed up in an abandoned mall, but I needed food so I headed out to fend for myself in the woods. I wasn't doing a great job of it, so I'm kinda glad you showed up.", - "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Okay, so, hear me out. This might sound crazy, but we're dealing with the walking dead, so I think I get a pass on that. You know your Greek mythology at all?", + "responses": [ + { "text": "Not really. How is that relevant?", "topic": "CWH_LEFT_FOR_DEAD_1_EXPLAIN" }, + { "text": "Sure, why?", "topic": "CWH_LEFT_FOR_DEAD_1_IDEAS2" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_1_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Okay, well, I know this sounds like an Indiana Jones B-plot, but I think someone found Pandora's Box, the actual thing or close to it. I think they tried to somehow harness it, to use the power in it for something. Maybe even something good, who knows, the power of the gods seems like it would be a green energy source to me. Whatever it was, they screwed it up, and released it for real. Not just a metaphorical thing like in the stories, but actually set the forces of Hades loose on Earth. Yeah, I know it's farfetched, but like I said: I think I get a pass on that.", + "responses": [ + { "text": "What? Pandora's box?", "topic": "CWH_LEFT_FOR_DEAD_1_EXPLAIN" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_1_EXPLAIN", + "type": "talk_topic", + "dynamic_line": "According to legend, Pandora was in the house of the gods and found an unopened box. She decided to investigate, and when she opened it and unthinkable horrors and diseases spilled out. Sound familiar?", + "responses": [ + { "text": "Sure, what's that go to do with anything?", "topic": "CWH_LEFT_FOR_DEAD_1_IDEAS2" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] } ] diff --git a/data/json/npcs/Backgrounds/left_for_dead_2.json b/data/json/npcs/Backgrounds/left_for_dead_2.json index 981701eb77d7d..8885d485adb3d 100644 --- a/data/json/npcs/Backgrounds/left_for_dead_2.json +++ b/data/json/npcs/Backgrounds/left_for_dead_2.json @@ -27,5 +27,21 @@ { "text": "Thanks for telling me all that. ", "topic": "TALK_FRIEND" }, { "text": "Thanks for telling me all that. ", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_2_IDEAS1", + "type": "talk_topic", + "dynamic_line": "You mean what caused the riots and all that? Well, they told us it was a Chinese bioweapon but I have troubles believing anyone could engineer a bioweapon that could do all this. The only answer I can come up with, silly though it sounds, is aliens.", + "responses": [ + { "text": "You think this is an invasion?", "topic": "CWH_LEFT_FOR_DEAD_2_IDEAS2" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_2_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Well, maybe, but I'd guess it's too disorganized to be a proper invasion. If I had to guess, I'd say there was something locked in the polar ice. Like, remember a few years back there was that big thing online about an alien body found in the ice? I don't know if you remember but it was all over the news for a while until it turned out to be a hoax. Only, since then, I've seen some aliens walking around that look a *lot* like that ice body. Maybe it wasn't a hoax, maybe that was a cover-up. So, maybe those aliens had some kind of virus. It went around the world and infected everything silently until, somehow, it activated and caused the violence and monsters and mutations.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/left_for_dead_3.json b/data/json/npcs/Backgrounds/left_for_dead_3.json new file mode 100644 index 0000000000000..ddaaaf7ce79b0 --- /dev/null +++ b/data/json/npcs/Backgrounds/left_for_dead_3.json @@ -0,0 +1,74 @@ +[ + { + "id": "BGSS_LEFT_FOR_DEAD_3_STORY1", + "type": "talk_topic", + "dynamic_line": "Let's not dance around it: I joined the riots, at first. I don't really remember what I was thinking. I'd protested stuff like police brutality before, but this was different. I didn't make a sign and go down there expecting to chant and march, I grabbed a bat and went outside planning to fuck shit up. I've never felt so angry before. The riots had already been going on a while at that point, and to me, it just looked like the government trying to squash the people again.", + "responses": [ + { "text": "Those rioters had a reputation for being absolutely psycho.", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY2" }, + { "text": "Not many people made it out of the riots alive.", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY3" }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_LEFT_FOR_DEAD_3_STORY2", + "type": "talk_topic", + "dynamic_line": "Yeah, you're telling me. The rioters… they weren't even like humans, let alone protestors. Nothing like any protest I'd ever been in before. That didn't stop me. I joined them, and I was as bad as a bunch of them. Smashed windows, beat up bystanders, burnt cars. I remember ripping riot gear off a cop and… nevermind. I don't want to remember that.", + "responses": [ + { "text": "How did you survive?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY3" }, + { "text": "What made you come back?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY4" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_LEFT_FOR_DEAD_3_STORY3", + "type": "talk_topic", + "dynamic_line": "At some point, I felt like I was waking up. It was around the time they were busting out those humvees with riot control turrets on top. Says something about my frame of mind that I don't even remember if I'd seen them before that point. Anyway I heard the gunfire going off and just kinda realized I was on the edges of a mob charging a heavily armed military emplacement. That's when I started seeing the mob for what it was, seeing the wild-eyed animals, even the zombies. I turned and ran.", + "responses": [ + { "text": "What made you come back?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY4" }, + { "text": "Where did you go from there?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY5" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_LEFT_FOR_DEAD_3_STORY4", + "type": "talk_topic", + "dynamic_line": "I honestly don't know. I wonder if some of the others would have come back to their senses, given time. I don't think I'm anything special. Maybe a lot of them did, and just weren't on the edge of the crowd at the time. I'll tell you, almost as soon as I came back to myself, I could see some of the rioters looking at me like I was prey. I didn't stick around to see what would happen.", + "responses": [ + { "text": "Where did you go from there?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY5" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "BGSS_LEFT_FOR_DEAD_3_STORY5", + "type": "talk_topic", + "dynamic_line": "I knew the city pretty well. I went for an abandoned building I knew about, headed through a broken window, and holed up in there for a few days. I had a fair bit of stolen food and I just kept to myself. When things started to quiet down, I headed out, and here I am.", + "responses": [ + { "text": "Thanks for telling me all that. ", "topic": "TALK_FRIEND" }, + { "text": "Thanks for telling me all that. ", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_3_IDEAS1", + "type": "talk_topic", + "dynamic_line": "So, I remember the time leading up to the riots, same as anyone. Things were bad, there were some really awful crimes being reported in the news, and there was a lot of racial tension as usual from the way the cops were handling it. Then people started rioting, which isn't unusual, but it was weird the kind of places that the riots were starting in. Like, upper middle class neighbourhoods, midwestern small towns, things like that. Anyway, I joined the riots and I don't remember a lot of clear stuff after that.", + "responses": [ + { "text": "You joined the riots?", "topic": "BGSS_LEFT_FOR_DEAD_3_STORY1" }, + { + "text": "You must have some insights into what caused all this, then.", + "topic": "CWH_LEFT_FOR_DEAD_3_IDEAS2" + }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_LEFT_FOR_DEAD_3_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Kinda, I guess. I heard people blaming the riots on some kind of mind control drug, and frankly I'm not sure that's far off base. That's kinda what it felt like, although the whole time I really felt like myself. It wasn't until I snapped out of it that I realized how weird it was. That doesn't explain anything else though: the zombies, the monsters, all this stuff is way off base. Anything I've tried to guess just sounds like bad science fiction, like demonic curses or alien weapons kinda stuff.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + } +] diff --git a/data/json/npcs/Backgrounds/no_past_1.json b/data/json/npcs/Backgrounds/no_past_1.json index 825764c371ba9..aefc1e8f46f84 100644 --- a/data/json/npcs/Backgrounds/no_past_1.json +++ b/data/json/npcs/Backgrounds/no_past_1.json @@ -4,5 +4,20 @@ "type": "talk_topic", "dynamic_line": "Before ? Who cares about that? This is a new world, and yeah, it's pretty . It's the one we've got though, so let's not dwell in the past when we should be making the best of what little we have left.", "responses": [ { "text": "I can respect that.", "topic": "TALK_FRIEND" } ] + }, + { + "id": "CWH_NO_PAST_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "I don't really want to talk about the time before, you know?", + "responses": [ + { "text": "Keep it vague if you want, but please, can you fill me in a little?", "topic": "CWH_NO_PAST_1_IDEAS2" }, + { "text": "Never mind then.", "topic": "TALK_FRIEND" } + ] + }, + { + "id": "CWH_NO_PAST_1_IDEAS2", + "type": "talk_topic", + "dynamic_line": "I - fine. Drugs in the water, some kind of bioweapon I guess. You know how things were with China, they blamed it on them mostly. Made people violent and ugly. There were riots. People I cared about joined them, and I guess I'll never know why. Riots led to military and police action, which made the riots worse. People acted like animals, not just the rioters but everyone. Then came the monsters and nightmares walking the world like real Armageddon, and everyone died, and started coming back as monsters themselves. There's your story. If you want more, talk to someone else.", + "responses": [ { "text": "Thanks for that.", "topic": "TALK_FRIEND" } ] } ] diff --git a/data/json/npcs/Backgrounds/no_past_2.json b/data/json/npcs/Backgrounds/no_past_2.json index 28f8010581e62..be7c226dee10c 100644 --- a/data/json/npcs/Backgrounds/no_past_2.json +++ b/data/json/npcs/Backgrounds/no_past_2.json @@ -1,8 +1,14 @@ [ + { + "id": "CWH_NO_PAST_2_IDEAS1", + "type": "talk_topic", + "dynamic_line": "To be honest… I don't really remember. I remember vague details of my life before the world was like this, but itself? It's all a blur. I think something pretty bad must have happened to me. I remember a few things: snatches of violence, something about a woman killing her baby. I feel like I'd rather not remember.", + "responses": [ { "text": "Huh.", "topic": "TALK_FRIEND" } ] + }, { "id": "BGSS_NO_PAST_2_STORY1", "type": "talk_topic", - "dynamic_line": "To be honest… I don't really remember. I remember vague details of my life before the world was like this, but itself? It's all a blur. I don't know how I got where I am now, or how any of this happened. I think something pretty bad must have happened to me. Or maybe I was just hit in the head really hard. Or both. Both seems likely.", + "dynamic_line": "To be honest… I don't really remember. I remember vague details of my life before the world was like this, but itself? It's all a blur. I don't know how I got where I am now, or how any of this happened. I think something pretty bad must have happened to me. Or maybe I was just hit in the head really hard. Or both. Both seems likely. First thing I remember is seeing an already-read text on my phone from the emergency government broadcast system, saying the United States had fallen.", "responses": [ { "text": "Huh.", "topic": "TALK_FRIEND" } ] } ] diff --git a/data/json/npcs/Backgrounds/no_past_4.json b/data/json/npcs/Backgrounds/no_past_4.json index 29f6f55b30de8..d4194568a047a 100644 --- a/data/json/npcs/Backgrounds/no_past_4.json +++ b/data/json/npcs/Backgrounds/no_past_4.json @@ -33,5 +33,44 @@ "type": "talk_topic", "dynamic_line": "Listen. I said it clearly, and if you keep picking at it I'm gonna get mad. Who I was is gone. Dead. I don't give a shit about your 'healthy', don't ask again.", "responses": [ { "text": "What were you saying before?", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_NO_PAST_4_IDEAS1", + "type": "talk_topic", + "dynamic_line": "You're asking me what I think caused all this? It was all over the news. Some kind of Chinese bio-weapon. It's no different from the pandemic a few years back, but this time they got the formula right. Maybe too right. Doesn't matter anyway, I hear it got out on them and wiped them out too. Serves em right.", + "responses": [ + { "text": "Can you tell me more about what actually went down, though?", "topic": "CWH_NO_PAST_4_IDEAS2" }, + { + "condition": { "or": [ { "u_has_perception": 7 }, { "u_has_intelligence": 8 } ] }, + "text": "How does that explain all the other crazy stuff?", + "topic": "CWH_NO_PAST_4_SKEPTIC" + }, + { "text": "", "topic": "TALK_NONE" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_NO_PAST_4_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Well, you know. First there were the riots from the mind-control drugs in the water. Except I think we can all see now it was actually a virus again. The military and the cops did their damndest to put it down but it got out of hand. Then the virus mutated and started bringing the dead back to life like in some kinda B-movie, and shit got really real. They let the big things loose, or they set them on us, I dunno. Huge unspeakable monsters… still makes me shudder to think of them. They obviously weren't built for combat though, and the military took 'em down fast.", + "responses": [ + { + "condition": { "or": [ { "u_has_perception": 7 }, { "u_has_intelligence": 8 } ] }, + "text": "How does that explain all the other crazy stuff?", + "topic": "CWH_NO_PAST_4_SKEPTIC" + }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_NO_PAST_4_SKEPTIC", + "type": "talk_topic", + "dynamic_line": "What? Of course it does. They started with a bioweapon and then it went full nuclear. Only the weapons we had now were a lot worse than H-bombs. Uncle Sam managed to beat back the really nasty stuff, but I guess it was with his dying breath.", + "responses": [ + { "text": "Can you tell me more about what actually went down, though?", "topic": "CWH_NO_PAST_4_IDEAS2" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] } ] diff --git a/data/json/npcs/Backgrounds/religious_1.json b/data/json/npcs/Backgrounds/religious_1.json index 5b3c7d9a11cde..93b87422af825 100644 --- a/data/json/npcs/Backgrounds/religious_1.json +++ b/data/json/npcs/Backgrounds/religious_1.json @@ -58,5 +58,21 @@ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_RELIGIOUS_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "It's clear enough, isn't it? That… that end, was the Rapture. I'm still here, and I still don't understand why, but I will keep Jesus in my heart through the Tribulations to come. When they're past, I'm sure He will welcome me into the Kingdom of Heaven. Or… or something along those lines.", + "responses": [ + { "text": "I meant more the actual events. What happened?", "topic": "CWH_RELIGIOUS_1_IDEAS2" }, + { "text": "", "topic": "TALK_FRIEND" }, + { "text": "", "topic": "TALK_DONE" } + ] + }, + { + "id": "CWH_RELIGIOUS_1_IDEAS2", + "type": "talk_topic", + "dynamic_line": "Oh. Well, I think it follows the good word in Revelations, if I remember right. I haven't talked to a preacher in a bit, you know. There were the plagues… the first one was the one a couple years ago, that big pandemic, that was when people started talking about the end being near. Then there was a plague of blood, or was it violence? That was the riots. Then the seas turned red with blood, that was from all the people being shot. Then a plague of fire, I remember that one for sure, that was when there were bombs and things going off everywhere to try to contain the riots. And then demons and monsters walked the Earth, and the dead rose from their graves, and finally the meek inherited. Clear as day.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/religious_2.json b/data/json/npcs/Backgrounds/religious_2.json index 738627e08696d..608a264499165 100644 --- a/data/json/npcs/Backgrounds/religious_2.json +++ b/data/json/npcs/Backgrounds/religious_2.json @@ -4,5 +4,11 @@ "type": "talk_topic", "dynamic_line": "Same as anyone. I turned away from God, and now I'm paying the price. The Rapture has come, and I was left behind. So now, I guess I wander through Hell on Earth. I wish I'd paid more attention in Sunday School.", "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_RELIGIOUS_2_IDEAS1", + "type": "talk_topic", + "dynamic_line": "Well, I guess that was the Rapture. It didn't play out how I thought it would. They made me think it was gonna be a flash of light and then *poof*, everyone's gone. Instead it was messy and dirty. Riots in the streets, the military and police serving the Antichrist to gun down the people like - what was it my dad used to say - like wheat before the chaff? Then when we'd really showed our Sin, God came in with the real plagues. The dead started walking, getting up with machine gun holes in them to fight the military, and the military started turning on each other too. After that, the legions of Hell itself came out. Huge monsters, worse than anything I'd ever imagined, just tore through the cities ripping everything to shreds. Then they started dying off as quick as they'd arrived, and we were left trying to run and hide from the undead. A day or two later the power started going out.", + "responses": [ { "text": "", "topic": "TALK_FRIEND" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/wedding_1.json b/data/json/npcs/Backgrounds/wedding_1.json index 6a15b083266e4..8eb2f0c19c0e4 100644 --- a/data/json/npcs/Backgrounds/wedding_1.json +++ b/data/json/npcs/Backgrounds/wedding_1.json @@ -33,6 +33,7 @@ { "id": "BGSS_WEDDING_1_CALM", "type": "talk_topic", + "//": "Some day it would be nice to have a demographically selected chance of this not being heteronormative", "dynamic_line": { "npc_female": true, "yes": "Well, I have this weird hope. It's probably stupid, but I saw my fiancé peel out of there with his sister - my maid of honor - in her pickup truck as things went bad. So, until I run into them again one way or another, I'm just gonna keep on believing they're out there, doing well. That's more than most of us have.", @@ -42,5 +43,11 @@ { "text": "What were you saying before that?", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] + }, + { + "id": "CWH_WEDDING_1_IDEAS1", + "type": "talk_topic", + "dynamic_line": "I'll be honest with you, I was paying more attention to wedding planning than current events leading up to things. I knew there were riots going on, but they were out of town. Even when they got closer to home, I tried to ignore them so we could have our big day. After the zombies started coming, though, well that's when stuff got really weird. When I was running from the wedding I swear I saw the sky rip open and monsters fly out of the hole, like something out of Independence Day. I don't know what it all was, it looked like black magic or something.", + "responses": [ { "text": "", "topic": "TALK_NONE" }, { "text": "", "topic": "TALK_DONE" } ] } ] diff --git a/data/json/npcs/Backgrounds/whathappened_table_of_contents.json b/data/json/npcs/Backgrounds/whathappened_table_of_contents.json new file mode 100644 index 0000000000000..5f7efe6ebc643 --- /dev/null +++ b/data/json/npcs/Backgrounds/whathappened_table_of_contents.json @@ -0,0 +1,111 @@ +[ + { + "id": "TALK_FRIEND_CONVERSATION", + "type": "talk_topic", + "//": "the 'CWH' prefix stands for 'Cataclysm: what happened', and refers to stories where NPCs answer your questions about what they think happened in the cataclysm.", + "responses": [ + { + "text": "", + "topic": "CWH_CONFUSED_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Confused_1" } + }, + { + "text": "", + "topic": "CWH_NO_PAST_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_No_Past_1" } + }, + { + "text": "", + "topic": "CWH_NO_PAST_2_IDEAS1", + "condition": { "npc_has_trait": "BGSS_No_Past_2" } + }, + { + "text": "", + "topic": "BGSS_NO_PAST_3_STORY1", + "//": "No_past_3'S amnesia story would be the same for either of these questions.", + "condition": { "npc_has_trait": "BGSS_No_Past_3" } + }, + { + "text": "", + "topic": "CWH_NO_PAST_4_IDEAS1", + "condition": { "npc_has_trait": "BGSS_No_Past_4" } + }, + { + "text": "", + "topic": "BGSS_NO_PAST_5_STORY1", + "//": "No_past_5'S unwillingness to talk about it would be the same for either of these questions.", + "condition": { "npc_has_trait": "BGSS_No_Past_5" } + }, + { + "text": "", + "topic": "CWH_RELIGIOUS_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Religious_1" } + }, + { + "text": "", + "topic": "CWH_RELIGIOUS_2_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Religious_2" } + }, + { + "text": "", + "topic": "CWH_DREAMER_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Dreamer" } + }, + { + "text": "", + "topic": "CWH_WEDDING_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Wedding_1" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_1" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_2_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_2" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_3_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_3" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_4_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_4" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_5_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_5" } + }, + { + "text": "", + "topic": "CWH_EVACUEE_6_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Evacuee_6" } + }, + { + "text": "", + "topic": "CWH_FEMA_EVACUEE_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_FEMA_Evacuee_1" } + }, + { + "text": "", + "topic": "CWH_LEFT_FOR_DEAD_1_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Left_for_Dead_1" } + }, + { + "text": "", + "topic": "CWH_LEFT_FOR_DEAD_2_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Left_for_Dead_2" } + }, + { + "text": "", + "topic": "CWH_LEFT_FOR_DEAD_3_IDEAS1", + "condition": { "npc_has_trait": "BGSS_Left_for_Dead_3" } + } + ] + } +] diff --git a/data/json/npcs/talk_tags.json b/data/json/npcs/talk_tags.json index 6f8b7f3142d7c..64a791efe598e 100644 --- a/data/json/npcs/talk_tags.json +++ b/data/json/npcs/talk_tags.json @@ -1147,6 +1147,16 @@ "Was it rough surviving thus far?" ] }, + { + "type": "snippet", + "category": "", + "//": "avatar response to an NPC that opens up their theories about what the cataclysm was.", + "text": [ + "How do you think we ended up here? What even happened?", + "What's going on? Like, big picture, what the hell happened?", + "Have you heard anything about how the apocalypse came about?" + ] + }, { "type": "snippet", "category": "", From 9e55433bae138cf6a1b8864d4ba1f7fc8b529cfc Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Tue, 30 Jun 2020 00:08:06 -0700 Subject: [PATCH 32/41] Adds Exodii monster stat blocks (no spawning yet) (#41446) --- data/json/harvest.json | 33 ++++ data/json/items/ammo/exodii.json | 10 ++ data/json/items/ammo_types.json | 6 + data/json/items/corpses/dead_exodii.json | 70 ++++++++ data/json/items/gun/exodii.json | 66 +++++++ data/json/items/magazine/exodii.json | 40 +++++ data/json/items/resources/alien.json | 91 ++++++++++ data/json/monster_factions.json | 7 + data/json/monsters/cyborgs.json | 127 +++++++++++++ data/json/monsters/drones.json | 56 ++++++ data/json/monsters/turrets.json | 47 +++++ data/json/recipes/recipe_deconstruction.json | 180 ++++++++++++++++++- data/json/species.json | 6 + 13 files changed, 738 insertions(+), 1 deletion(-) create mode 100644 data/json/items/ammo/exodii.json create mode 100644 data/json/items/corpses/dead_exodii.json create mode 100644 data/json/items/gun/exodii.json create mode 100644 data/json/items/magazine/exodii.json diff --git a/data/json/harvest.json b/data/json/harvest.json index ff13b39e5fea7..8f8260e570ff7 100644 --- a/data/json/harvest.json +++ b/data/json/harvest.json @@ -88,6 +88,39 @@ { "drop": "scrap", "base_num": [ 1, 5 ], "scale_num": [ 0.3, 0.7 ], "max": 12, "type": "bone" } ] }, + { + "id": "mon_zomborg", + "type": "harvest", + "message": "You search for any salvageable hardware in what's left of this flesh and metal monster", + "entries": [ + { + "drop": "bio_power_storage", + "type": "bionic", + "flags": [ "FILTHY", "NO_STERILE", "NO_PACKED" ], + "faults": [ "fault_bionic_salvaged" ] + }, + { + "drop": "bionics_common", + "type": "bionic_group", + "flags": [ "FILTHY", "NO_STERILE", "NO_PACKED" ], + "faults": [ "fault_bionic_salvaged" ] + }, + { + "drop": "bionics", + "type": "bionic_group", + "flags": [ "FILTHY", "NO_STERILE", "NO_PACKED" ], + "faults": [ "fault_bionic_salvaged" ], + "base_num": [ 0, 1 ] + }, + { "drop": "meat_tainted", "type": "flesh", "mass_ratio": 0.1 }, + { "drop": "fat_tainted", "type": "flesh", "mass_ratio": 0.04 }, + { "drop": "bone_tainted", "type": "bone", "mass_ratio": 0.05 }, + { "drop": "sinew", "type": "bone", "mass_ratio": 0.001 }, + { "drop": "cable", "base_num": [ 1, 3 ], "scale_num": [ 0.2, 0.6 ], "max": 8, "type": "flesh" }, + { "drop": "e_scrap", "base_num": [ 1, 5 ], "scale_num": [ 0.3, 0.7 ], "max": 12, "type": "bone" }, + { "drop": "scrap", "base_num": [ 1, 5 ], "scale_num": [ 0.3, 0.7 ], "max": 12, "type": "bone" } + ] + }, { "id": "mammal_tiny", "//": "animals so tiny they don't drop chunks of meat", diff --git a/data/json/items/ammo/exodii.json b/data/json/items/ammo/exodii.json new file mode 100644 index 0000000000000..ba09a03a8e62d --- /dev/null +++ b/data/json/items/ammo/exodii.json @@ -0,0 +1,10 @@ +[ + { + "id": "123ln", + "type": "AMMO", + "copy-from": "3006", + "name": { "str": "12.3ln round" }, + "description": "The 12.3ln cartridge was introduced in Romania in the wake of the second Carpathian conflict. The PA md. 71 rifle using this ammunition rapidly gained popularity in the Eastern Union, and from there, the world. Due to this, the 12.3ln rapidly became the standard combat round in the Eurasian sphere. It was easily scavenged and stockpiled by the Exodii. To you, it looks and feels quite similar to a .30-06 Springfield cartridge, but with a slightly sharper taper.", + "ammo_type": "123ln" + } +] diff --git a/data/json/items/ammo_types.json b/data/json/items/ammo_types.json index 533ea1f065132..58ea87677cfcc 100644 --- a/data/json/items/ammo_types.json +++ b/data/json/items/ammo_types.json @@ -652,5 +652,11 @@ "id": "300blk", "name": ".300 AAC Blackout", "default": "300blk" + }, + { + "type": "ammunition_type", + "id": "123ln", + "name": "12.3ln cartridge", + "default": "123ln" } ] diff --git a/data/json/items/corpses/dead_exodii.json b/data/json/items/corpses/dead_exodii.json new file mode 100644 index 0000000000000..e9ab4538932a2 --- /dev/null +++ b/data/json/items/corpses/dead_exodii.json @@ -0,0 +1,70 @@ +[ + { + "type": "GENERIC", + "id": "broken_exodii_worker", + "symbol": ",", + "color": "light_gray", + "name": "broken exodii worker", + "category": "other", + "description": "A broken exodii worker. It's possible it could be gutted for parts.", + "price": 1000, + "material": [ "steel" ], + "volume": "119 L", + "weight": "221 kg", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + }, + { + "type": "GENERIC", + "id": "broken_exodii_quad", + "symbol": ",", + "color": "light_gray", + "name": "broken exodii quadruped", + "category": "other", + "description": "A broken exodii walker. Still looks intimidating despite being permanently inoperative, possibly due to the sheer size and mass. Could be gutted for parts.", + "price": 1000, + "material": [ "steel" ], + "volume": "410 L", + "weight": "498 kg", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + }, + { + "type": "GENERIC", + "id": "broken_exodii_turret", + "symbol": ",", + "color": "yellow", + "name": "broken exodii turret", + "category": "other", + "description": "A broken exodii turret. Still looks intimidating despite being permanently inoperative, possibly due to the sheer size and mass. Could be gutted for parts.", + "price": 1000, + "material": [ "steel" ], + "weight": "206 kg", + "volume": "105 L", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + }, + { + "type": "GENERIC", + "id": "broken_exodii_sniper_drone", + "symbol": ",", + "color": "yellow", + "name": "broken exodii balloon-drone", + "category": "other", + "description": "A broken balloon drone. The balloon has been shredded, but most of the chassis is still intact. Could be gutted for parts.", + "price": 1000, + "material": [ "steel" ], + "volume": "70 L", + "weight": "150 kg", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + } +] diff --git a/data/json/items/gun/exodii.json b/data/json/items/gun/exodii.json new file mode 100644 index 0000000000000..8342b7e18ef4b --- /dev/null +++ b/data/json/items/gun/exodii.json @@ -0,0 +1,66 @@ +[ + { + "id": "pamd68", + "looks_like": "ar15", + "type": "GUN", + "reload_noise_volume": 10, + "name": { "str": "PA md. 68 Battle Rifle" }, + "description": "The most popular gun to use the 12.3ln cartridge was, of course, the PA md. 71. Its predecessor, the md. 68, was viewed by many as a sort of failure: although it was reliable and powerful, it was too heavy to be used as a good infantry weapon, and not really heavy enough to be a good support gun. Enough were made, though, that during the zombie apocalypse, it gained a great deal of resurgent popularity as a light emplacement gun that used readily available ammunition. It perfectly served the purposes of the Exodii, who had far less concern about its unwieldiness.", + "weight": "9480 g", + "volume": "2800 ml", + "price": 350000, + "price_postapoc": 4000, + "to_hit": -3, + "bashing": 12, + "material": [ "steel", "aluminum" ], + "symbol": "(", + "color": "dark_gray", + "ammo": [ "123ln" ], + "skill": "rifle", + "dispersion": 190, + "durability": 9, + "min_cycle_recoil": 3820, + "modes": [ [ "DEFAULT", "auto", 2 ], [ "AUTO", "auto", 5 ] ], + "barrel_length": "1200 ml", + "faults": [ "fault_gun_blackpowder", "fault_gun_dirt", "fault_gun_chamber_spent" ], + "pocket_data": [ + { + "pocket_type": "MAGAZINE_WELL", + "holster": true, + "max_contains_volume": "20 L", + "max_contains_weight": "20 kg", + "item_restriction": [ "exodiiBRmag" ] + } + ] + }, + { + "id": "pamd71z", + "copy-from": "rifle_manual", + "looks_like": "ar15", + "type": "GUN", + "name": { "str": "PA md. 71 zombie hunting rifle" }, + "description": "This extremely popular Romanian assault rifle, made famous in the third Carpachian War, has been redesigned slightly by the Exodii to serve as a sniper weapon. It is well suited to precision shots against high-priority targets. This modified design fires an extremely rapid 5-shot burst, with the goal of shredding the target and preventing revivification.", + "weight": "3910 g", + "volume": "3 L", + "price": 80000, + "price_postapoc": 3250, + "to_hit": -1, + "bashing": 12, + "material": [ "steel", "aluminum" ], + "color": "light_gray", + "ammo": [ "123ln" ], + "dispersion": 100, + "durability": 8, + "modes": [ [ "DEFAULT", "auto", 5 ] ], + "barrel_length": "250 ml", + "pocket_data": [ + { + "pocket_type": "MAGAZINE_WELL", + "holster": true, + "max_contains_volume": "20 L", + "max_contains_weight": "20 kg", + "item_restriction": [ "exodiiminimag" ] + } + ] + } +] diff --git a/data/json/items/magazine/exodii.json b/data/json/items/magazine/exodii.json new file mode 100644 index 0000000000000..446d8e8129d25 --- /dev/null +++ b/data/json/items/magazine/exodii.json @@ -0,0 +1,40 @@ +[ + { + "id": "exodiiminimag", + "looks_like": "garandclip", + "type": "MAGAZINE", + "name": { "str": "PA Md. 71 Exodii 12.3ln magazine" }, + "description": "A small, sleek magazine based on a classic PA Md. 71 clip, with some redesigns by the Exodii for better use in lighter-than-air drones. Its small size is less appropriate for ground-fighting of hordes of zombies, as it is a bit inconvenient to reload.", + "weight": "30 g", + "volume": "250 ml", + "price": 600, + "price_postapoc": 50, + "material": [ "steel" ], + "symbol": "#", + "color": "light_gray", + "ammo_type": [ "123ln" ], + "capacity": 10, + "reload_time": 220, + "flags": [ "MAG_COMPACT" ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "123ln": 10 } } ] + }, + { + "id": "exodiiBRmag", + "looks_like": "stanag30", + "type": "MAGAZINE", + "name": { "str": "PA Md. 68 Exodii 12.3ln magazine" }, + "description": "An unreasonably large magazine for the already heavy PA Md. 68 battle rifle, custom designed and manufactured by the Exodii.", + "weight": "600 g", + "volume": "1250 ml", + "price": 10500, + "price_postapoc": 450, + "material": [ "steel" ], + "symbol": "#", + "color": "light_gray", + "ammo_type": [ "123ln" ], + "capacity": 60, + "reload_time": 180, + "flags": [ "MAG_BULKY" ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "123ln": 60 } } ] + } +] diff --git a/data/json/items/resources/alien.json b/data/json/items/resources/alien.json index 34217f32a970e..67e06a51fab9e 100644 --- a/data/json/items/resources/alien.json +++ b/data/json/items/resources/alien.json @@ -28,5 +28,96 @@ "symbol": "0", "color": "light_blue", "flags": [ "NO_SALVAGE" ] + }, + { + "type": "GENERIC", + "id": "exodii_chassis", + "name": { "str_sp": "Exodii chassis" }, + "description": "This roughly hexagonal frame and associated bodywork looks like it was constructed as a single monolithic piece. The fitting holes and attachments are extremely durable, despite showing signs of heavy wear and repair. The structure is versatile, and could probably be engineered to serve a number of different heavy combat roles.", + "symbol": "c", + "color": "light_gray", + "weight": "500 kg", + "volume": "700 L", + "price": 1000000, + "material": [ "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "exodii_drone_chassis", + "name": { "str_sp": "Exodii drone chassis" }, + "description": "This small, roughly hexagonal frame and associated bodywork looks like it was constructed as a single monolithic piece. The fitting holes and attachments are extremely durable, despite showing signs of heavy wear and repair. The structure is versatile, and could probably be engineered to serve a number of different heavy combat roles.", + "symbol": "c", + "color": "light_gray", + "weight": "40 kg", + "volume": "150 L", + "price": 100000, + "material": [ "steel", "aluminum" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "cyborg_matrix", + "name": { "str": "cybernetic neural matrix", "str_pl": "cybernetic neural matrices" }, + "description": "A series of tanks and tubes with ports for fluids, electricity, and input and output, this complex arrangement is made to house a brain and spine and the most difficult to replace organs for keeping them alive.", + "symbol": "m", + "color": "light_blue", + "weight": "20 kg", + "volume": "10 L", + "price": 10000, + "material": [ "plastic", "aluminum", "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "exodii_computer", + "name": { "str": "unfamiliar electronic thingy" }, + "description": "The wiring and general shape suggest to you that this is a computer, or at least some sort of electronic device, but what it is and what role it serves is lost on you. It's heavy and sturdy in construction.", + "symbol": "p", + "color": "dark_gray", + "weight": "10 kg", + "volume": "10 L", + "price": 10000, + "material": [ "plastic", "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "exodii_module", + "name": { "str": "inscribed metal plates" }, + "description": "This device looks electronic, but is unfamiliar. It is a series of tightly fitted coppery-looking rings, set concentrically. Wires run from each ring to an axis in the middle.", + "symbol": "i", + "color": "dark_gray", + "weight": "1 kg", + "volume": "1 L", + "price": 1000, + "material": [ "copper", "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "exodii_sensor", + "name": { "str": "cybernetic sensor" }, + "description": "From the large glassy eye - the size of a small dinner plate - in the front, you deduce this is some sort of camera. None of the inner workings make any sense to you nor resemble any camera you've seen before.", + "symbol": ")", + "color": "blue", + "weight": "5 kg", + "volume": "3 L", + "price": 20000, + "material": [ "steel", "plastic" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "exodii_motor", + "name": { "str": "rotary device" }, + "description": "You assume from the coils of coppery wire and the protruding piston that this is some sort of motor or generator, but the design doesn't look similar to anything you've seen before, and you can't figure out how to get it to work.", + "symbol": "o", + "color": "blue", + "weight": "2 kg", + "volume": "500 ml", + "price": 2000, + "material": [ "steel", "copper" ], + "category": "spare_parts" } ] diff --git a/data/json/monster_factions.json b/data/json/monster_factions.json index 70a1991aad9d6..510b9501d9a28 100644 --- a/data/json/monster_factions.json +++ b/data/json/monster_factions.json @@ -71,6 +71,13 @@ "base_faction": "bot", "neutral": [ "cop_bot", "military", "utility_bot", "science", "small_animal" ] }, + { + "type": "MONSTER_FACTION", + "name": "exodii", + "neutral": [ "bot" ], + "by_mood": [ "animal", "nether" ], + "hate": [ "zombie", "fungus", "cult", "triffid" ] + }, { "type": "MONSTER_FACTION", "name": "science", diff --git a/data/json/monsters/cyborgs.json b/data/json/monsters/cyborgs.json index 37a7a628f462b..c344640b827d5 100644 --- a/data/json/monsters/cyborgs.json +++ b/data/json/monsters/cyborgs.json @@ -85,5 +85,132 @@ "PATH_AVOID_DANGER_2", "PRIORITIZE_TARGETS" ] + }, + { + "id": "mon_exodii_worker", + "type": "MONSTER", + "name": "Exodii worker", + "description": "This is a mostly humanoid robot equipped with various construction tools.", + "default_faction": "exodii", + "volume": "119 L", + "weight": "221 kg", + "species": [ "CYBORG" ], + "bodytype": "human", + "material": [ "steel" ], + "speed": 110, + "symbol": "e", + "morale": 20, + "aggression": -20, + "hp": 125, + "color": "light_gray", + "melee_skill": 8, + "melee_dice": 2, + "melee_dice_sides": 6, + "melee_cut": 12, + "armor_bash": 12, + "armor_cut": 28, + "vision_day": 50, + "vision_night": 10, + "revert_to_itype": "e_scrap", + "anger_triggers": [ "FRIEND_ATTACKED", "FRIEND_DIED", "HURT" ], + "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ] }, + "death_function": [ "BROKEN" ], + "flags": [ "SEES", "HEARS", "GOODHEARING", "NOHEAD", "NO_BREATHE", "PATH_AVOID_DANGER_2", "PRIORITIZE_TARGETS", "HIT_AND_RUN" ] + }, + { + "id": "mon_exodii_quad", + "type": "MONSTER", + "name": "Exodii quadruped", + "description": "This enormous quadrupedal robot seems to be cobbled together from parts, most of them unfamiliar to you. It moves with a heavy, oddly graceful gait, its footsteps leaving shallow craters behind. It bristles with an arsenal of weaponry, but doesn't seem in a particular rush to target you.", + "default_faction": "exodii", + "volume": "413 L", + "weight": "517 kg", + "species": [ "CYBORG" ], + "bodytype": "dog", + "material": [ "steel" ], + "speed": 110, + "symbol": "M", + "aggression": -5, + "morale": 70, + "hp": 240, + "color": "light_gray", + "melee_skill": 10, + "melee_dice": 3, + "melee_dice_sides": 8, + "melee_cut": 12, + "armor_bash": 42, + "armor_cut": 48, + "vision_day": 50, + "vision_night": 20, + "revert_to_itype": "e_scrap", + "starting_ammo": { "123ln": 3000 }, + "anger_triggers": [ "FRIEND_ATTACKED", "FRIEND_DIED", "HURT" ], + "special_attacks": [ + [ "FLAMETHROWER", 10 ], + { + "type": "gun", + "cooldown": 1, + "move_cost": 150, + "gun_type": "pamd68", + "ammo_type": "123ln", + "fake_skills": [ [ "gun", 5 ], [ "rifle", 8 ] ], + "fake_dex": 12, + "ranges": [ [ 0, 41, "DEFAULT" ] ], + "require_targeting_npc": true, + "require_targeting_monster": true, + "laser_lock": false, + "targeting_cost": 400, + "targeting_timeout_extend": -10, + "no_ammo_sound": "a chk!" + } + ], + "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ] }, + "death_function": [ "BROKEN" ], + "flags": [ "SEES", "HEARS", "GOODHEARING", "NOHEAD", "NO_BREATHE", "PATH_AVOID_DANGER_2", "PRIORITIZE_TARGETS", "HIT_AND_RUN" ] + }, + { + "id": "mon_zomborg", + "type": "MONSTER", + "name": "zomborg", + "description": "A mix of dead human and even deader technology, this twisted mess of steel and flesh moves like a puppet in the hands of an angry toddler. Its robotic components seem to have shut down, and new bands of flesh have wrapped around them, tugging and pulling them in awkward directions. Bits of metallic skeleton and armor plating jut from its decaying flesh.", + "default_faction": "zombie", + "looks_like": "mon_exodii_worker", + "volume": "120 L", + "weight": "200 kg", + "species": [ "CYBORG", "ZOMBIE" ], + "bodytype": "human", + "material": [ "steel", "flesh" ], + "speed": 60, + "symbol": "Z", + "morale": 100, + "aggression": 100, + "hp": 125, + "color": "light_gray", + "melee_skill": 3, + "melee_dice": 2, + "melee_dice_sides": 6, + "melee_cut": 12, + "armor_bash": 12, + "armor_cut": 28, + "vision_night": 3, + "special_attacks": [ { "type": "bite", "cooldown": 5 }, [ "GRAB", 7 ], [ "scratch", 20 ] ], + "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ] }, + "death_function": [ "FIREBALL" ], + "harvest": "mon_zomborg", + "flags": [ + "SEES", + "HEARS", + "SMELLS", + "STUMBLES", + "WARM", + "BASHES", + "GROUP_BASH", + "POISON", + "BLEED", + "NO_BREATHE", + "REVIVES", + "PUSH_MON", + "FILTHY" + ] } ] diff --git a/data/json/monsters/drones.json b/data/json/monsters/drones.json index 3f93e922992a4..e902291d66fe5 100644 --- a/data/json/monsters/drones.json +++ b/data/json/monsters/drones.json @@ -129,5 +129,61 @@ "revert_to_itype": "bot_mininuke_hack", "starting_ammo": { "mininuke": 1 }, "special_attacks": [ [ "KAMIKAZE", 0 ] ] + }, + { + "abstract": "exodii_sniper_drone", + "type": "MONSTER", + "name": { "str": "balloon sniper-drone" }, + "description": "This unusual contraption looks like a combination of a weather balloon and a quadcopter. Beneath the crude box containing its components hangs a small articulated rig wielding an integrated rifle. Its propellers flicker to life briefly, then shut down again, keeping it mostly stationary despite the air currents. It looks capable of hanging in the air for quite a long time before running out of power.", + "default_faction": "exodii", + "species": [ "ROBOT" ], + "volume": "5000 L", + "weight": "150 kg", + "//": "weight and dimensions based on the approx. size of a Griff 350, which is a commercial cargo-hauling quadcopter. Then I added a large balloon on top.", + "hp": 20, + "speed": 70, + "armor_bash": 4, + "armor_cut": 3, + "material": [ "aluminum", "steel" ], + "symbol": "e", + "color": "light_green", + "aggression": -20, + "morale": 70, + "vision_day": 50, + "vision_night": 20, + "starting_ammo": { "123ln": 10 }, + "anger_triggers": [ "FRIEND_ATTACKED", "FRIEND_DIED", "HURT" ], + "special_attacks": [ + { + "type": "gun", + "cooldown": 1, + "move_cost": 350, + "gun_type": "pamd71z", + "ammo_type": "123ln", + "fake_skills": [ [ "gun", 6 ], [ "rifle", 9 ] ], + "fake_dex": 12, + "ranges": [ [ 0, 50, "DEFAULT" ] ], + "require_targeting_npc": true, + "require_targeting_monster": true, + "laser_lock": true, + "targeting_cost": 700, + "targeting_timeout_extend": -10, + "no_ammo_sound": "tick!" + } + ], + "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ] }, + "death_function": [ "BROKEN" ], + "flags": [ + "SEES", + "HEARS", + "FLIES", + "NOHEAD", + "ELECTRONIC", + "NO_BREATHE", + "INTERIOR_AMMO", + "PATH_AVOID_DANGER_2", + "PRIORITIZE_TARGETS", + "HIT_AND_RUN" + ] } ] diff --git a/data/json/monsters/turrets.json b/data/json/monsters/turrets.json index 2806aa27da25b..0b2ba2b7bfd0f 100644 --- a/data/json/monsters/turrets.json +++ b/data/json/monsters/turrets.json @@ -331,5 +331,52 @@ "death_function": [ "BROKEN" ], "death_drops": { "groups": [ [ "turret_speaker", 1 ] ] }, "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "IMMOBILE", "NO_BREATHE" ] + }, + { + "id": "mon_exodii_turret", + "type": "MONSTER", + "name": "upcycled turret", + "description": "This hefty turret appears to be bolted together out of various scraps of technology, many of them extremely foreign looking. It is equipped with a hefty looking machine gun.", + "default_faction": "exodii", + "weight": "206 kg", + "volume": "105 L", + "hp": 240, + "speed": 100, + "material": [ "steel" ], + "symbol": "2", + "color": "light_gray", + "aggression": -10, + "morale": 100, + "armor_bash": 24, + "armor_cut": 26, + "vision_day": 50, + "vision_night": 20, + "luminance": 1, + "starting_ammo": { "123ln": 3000 }, + "anger_triggers": [ "FRIEND_ATTACKED", "FRIEND_DIED", "HURT" ], + "special_attacks": [ + { + "type": "gun", + "cooldown": 1, + "move_cost": 150, + "gun_type": "pamd68", + "ammo_type": "123ln", + "fake_skills": [ [ "gun", 5 ], [ "rifle", 8 ] ], + "fake_dex": 12, + "ranges": [ [ 0, 41, "DEFAULT" ] ], + "require_targeting_npc": true, + "require_targeting_monster": true, + "laser_lock": false, + "targeting_cost": 400, + "targeting_timeout_extend": -10, + "targeting_sound": "\"Beep.\"", + "targeting_volume": 20, + "no_ammo_sound": "a chk!" + } + ], + "special_when_hit": [ "RETURN_FIRE", 100 ], + "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ] }, + "death_function": [ "BROKEN" ], + "flags": [ "SEES", "HEARS", "GOODHEARING", "NOHEAD", "IMMOBILE", "NO_BREATHE", "PRIORITIZE_TARGETS", "INTERIOR_AMMO" ] } ] diff --git a/data/json/recipes/recipe_deconstruction.json b/data/json/recipes/recipe_deconstruction.json index 28b875b32c929..f783464cbbb6d 100644 --- a/data/json/recipes/recipe_deconstruction.json +++ b/data/json/recipes/recipe_deconstruction.json @@ -1158,6 +1158,183 @@ [ [ "storage_battery", 1 ] ] ] }, + { + "result": "broken_exodii_worker", + "type": "uncraft", + "skill_used": "electronics", + "skills_required": [ [ "mechanics", 9 ], [ "computer", 9 ] ], + "difficulty": 9, + "time": "8 h", + "using": [ [ "soldering_standard", 30 ], [ "welding_standard", 20 ] ], + "qualities": [ + { "id": "SCREW", "level": 1 }, + { "id": "SCREW_FINE", "level": 1 }, + { "id": "WRENCH", "level": 2 }, + { "id": "WRENCH_FINE", "level": 1 }, + { "id": "HAMMER", "level": 3 }, + { "id": "SAW_M", "level": 1 } + ], + "components": [ + [ [ "android_legs", 1 ] ], + [ [ "android_chassis", 1 ] ], + [ [ "android_arms", 1 ] ], + [ [ "self_monitoring_module", 1 ] ], + [ [ "exodii_sensor", 1 ] ], + [ [ "exodii_computer", 1 ] ], + [ [ "exodii_module", 2 ] ], + [ [ "exodii_motor", 6 ] ], + [ [ "power_supply", 3 ] ], + [ [ "amplifier", 1 ] ], + [ [ "e_scrap", 10 ] ], + [ [ "clockworks", 1 ] ], + [ [ "steel_chunk", 2 ] ], + [ [ "scrap", 2 ] ], + [ [ "cyborg_matrix", 1 ] ], + [ [ "storage_battery", 1 ] ], + [ [ "plut_cell", 2 ] ], + [ [ "steel_armor", 2 ] ], + [ [ "sheet_metal_small", 6 ] ], + [ [ "motor", 1 ] ], + [ [ "cable", 2 ] ], + [ [ "solder_wire", 20 ] ] + ] + }, + { + "result": "broken_exodii_quad", + "type": "uncraft", + "skill_used": "electronics", + "skills_required": [ [ "mechanics", 9 ], [ "computer", 9 ] ], + "difficulty": 9, + "time": "10 h", + "using": [ [ "soldering_standard", 60 ], [ "welding_standard", 30 ] ], + "qualities": [ + { "id": "SCREW", "level": 1 }, + { "id": "SCREW_FINE", "level": 1 }, + { "id": "WRENCH", "level": 2 }, + { "id": "WRENCH_FINE", "level": 1 }, + { "id": "HAMMER", "level": 3 }, + { "id": "SAW_M", "level": 1 } + ], + "components": [ + [ [ "sensor_module", 1 ] ], + [ [ "spidery_legs_big", 2 ] ], + [ [ "exodii_chassis", 1 ] ], + [ [ "targeting_module", 1 ] ], + [ [ "self_monitoring_module", 1 ] ], + [ [ "exodii_sensor", 2 ] ], + [ [ "exodii_computer", 1 ] ], + [ [ "exodii_module", 2 ] ], + [ [ "exodii_motor", 8 ] ], + [ [ "gun_module", 3 ] ], + [ [ "flamethrower", 1 ] ], + [ [ "tazer", 1 ] ], + [ [ "m4a1", 1 ] ], + [ [ "pamd68", 1 ] ], + [ [ "power_supply", 20 ] ], + [ [ "amplifier", 5 ] ], + [ [ "e_scrap", 50 ] ], + [ [ "clockworks", 4 ] ], + [ [ "steel_chunk", 10 ] ], + [ [ "scrap", 10 ] ], + [ [ "cyborg_matrix", 1 ] ], + [ [ "storage_battery", 2 ] ], + [ [ "plut_cell", 4 ] ], + [ [ "mil_plate", 2 ] ], + [ [ "hard_steel_armor", 10 ] ], + [ [ "sheet_metal_small", 40 ] ], + [ [ "motor", 1 ] ], + [ [ "cable", 10 ] ], + [ [ "omnicamera", 1 ] ], + [ [ "betavoltaic", 20 ] ], + [ [ "solder_wire", 20 ] ] + ] + }, + { + "result": "broken_exodii_turret", + "type": "uncraft", + "skill_used": "electronics", + "skills_required": [ [ "mechanics", 9 ], [ "computer", 9 ] ], + "difficulty": 9, + "time": "8 h", + "using": [ [ "soldering_standard", 60 ], [ "welding_standard", 30 ] ], + "qualities": [ + { "id": "SCREW", "level": 1 }, + { "id": "SCREW_FINE", "level": 1 }, + { "id": "WRENCH", "level": 2 }, + { "id": "WRENCH_FINE", "level": 1 }, + { "id": "HAMMER", "level": 3 }, + { "id": "SAW_M", "level": 1 } + ], + "components": [ + [ [ "turret_chassis", 1 ] ], + [ [ "identification_module", 1 ] ], + [ [ "self_monitoring_module", 1 ] ], + [ [ "exodii_computer", 1 ] ], + [ [ "exodii_module", 3 ] ], + [ [ "exodii_sensor", 2 ] ], + [ [ "exodii_motor", 4 ] ], + [ [ "gun_module", 2 ] ], + [ [ "targeting_module", 1 ] ], + [ [ "pamd68", 1 ] ], + [ [ "flamethrower", 1 ] ], + [ [ "storage_battery", 1 ] ], + [ [ "plut_cell", 4 ] ], + [ [ "power_supply", 10 ] ], + [ [ "amplifier", 3 ] ], + [ [ "e_scrap", 30 ] ], + [ [ "clockworks", 6 ] ], + [ [ "steel_chunk", 10 ] ], + [ [ "scrap", 15 ] ], + [ [ "mil_plate", 2 ] ], + [ [ "hard_steel_armor", 6 ] ], + [ [ "sheet_metal_small", 40 ] ], + [ [ "motor", 1 ] ], + [ [ "cable", 25 ] ], + [ [ "omnicamera", 1 ] ], + [ [ "betavoltaic", 40 ] ], + [ [ "solder_wire", 20 ] ] + ] + }, + { + "result": "broken_exodii_sniper_drone", + "type": "uncraft", + "skill_used": "electronics", + "skills_required": [ [ "mechanics", 9 ], [ "computer", 9 ] ], + "difficulty": 9, + "time": "8 h", + "using": [ [ "soldering_standard", 50 ], [ "welding_standard", 20 ] ], + "qualities": [ + { "id": "SCREW", "level": 1 }, + { "id": "SCREW_FINE", "level": 1 }, + { "id": "WRENCH", "level": 2 }, + { "id": "WRENCH_FINE", "level": 1 }, + { "id": "HAMMER", "level": 3 }, + { "id": "SAW_M", "level": 1 } + ], + "components": [ + [ [ "exodii_drone_chassis", 1 ] ], + [ [ "exodii_computer", 1 ] ], + [ [ "exodii_module", 1 ] ], + [ [ "exodii_sensor", 1 ] ], + [ [ "exodii_motor", 1 ] ], + [ [ "gun_module", 1 ] ], + [ [ "targeting_module", 1 ] ], + [ [ "pamd71z", 1 ] ], + [ [ "small_storage_battery", 1 ] ], + [ [ "plut_cell", 2 ] ], + [ [ "power_supply", 1 ] ], + [ [ "amplifier", 1 ] ], + [ [ "e_scrap", 20 ] ], + [ [ "clockworks", 2 ] ], + [ [ "scrap", 10 ] ], + [ [ "sheet_metal_small", 20 ] ], + [ [ "quad_rotors", 2 ] ], + [ [ "omnicamera", 1 ] ], + [ [ "betavoltaic", 5 ] ], + [ [ "plastic_sheet", 8 ] ], + [ [ "solder_wire", 3 ] ] + ] + }, { "result": "broken_dispatch_military", "type": "uncraft", @@ -1179,7 +1356,8 @@ [ [ "plut_cell", 1 ] ], [ [ "broken_manhack", 4 ] ], [ [ "omnicamera", 1 ] ], - [ [ "storage_battery", 1 ] ] + [ [ "storage_battery", 1 ] ], + [ [ "solder_wire", 20 ] ] ] }, { diff --git a/data/json/species.json b/data/json/species.json index 4b3fef2d02a05..0122bda32e612 100644 --- a/data/json/species.json +++ b/data/json/species.json @@ -17,6 +17,12 @@ "description": "a bird", "fear_triggers": [ "HURT", "SOUND" ] }, + { + "type": "SPECIES", + "id": "CYBORG", + "description": "an alien cyborg", + "footsteps": "heavy thuds." + }, { "type": "SPECIES", "id": "REPTILE", From 4be460fb797d8d988222fd3882163c2cfa0f4d88 Mon Sep 17 00:00:00 2001 From: Eric Pierce Date: Tue, 30 Jun 2020 01:08:46 -0600 Subject: [PATCH 33/41] Fill matches, lighters, needles, and other items for starting professions (#41643) * Start with filled lighter/phone/needle/matches This commit re-fills several starting items that had become empty, such that they now spawn full of charges: - matches (20 match) - UPS smartphone (120 battery) - refillable lighter (50 gasoline) - wood needle (200 thread) - bone needle (200 sinew) Fix #40819 * Make gasoline lantern and oil lamp watertight This allows the lanterns to contain fuel, and to spawn filled, particularly when a starting profession has a lantern or lamp. * Give Camper profession filled lantern and canteen --- data/json/items/tool/lighting.json | 4 +- data/json/professions.json | 452 ++++++++++++++--------------- 2 files changed, 212 insertions(+), 244 deletions(-) diff --git a/data/json/items/tool/lighting.json b/data/json/items/tool/lighting.json index 2213ecebe391b..531d52cee4e26 100644 --- a/data/json/items/tool/lighting.json +++ b/data/json/items/tool/lighting.json @@ -256,7 +256,7 @@ "symbol": ";", "color": "yellow", "ammo": [ "gasoline" ], - "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "gasoline": 500 } } ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "watertight": true, "ammo_restriction": { "gasoline": 500 } } ], "initial_charges": 500, "max_charges": 500, "charges_per_use": 1, @@ -507,7 +507,7 @@ "symbol": ";", "color": "yellow", "ammo": [ "lamp_oil" ], - "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "lamp_oil": 750 } } ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "watertight": true, "ammo_restriction": { "lamp_oil": 750 } } ], "initial_charges": 750, "max_charges": 750, "charges_per_use": 1, diff --git a/data/json/professions.json b/data/json/professions.json index 46ab2256392c2..66f8cebed9c77 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -17,6 +17,12 @@ "id": "charged_cell_phone", "entries": [ { "item": "light_plus_battery_cell", "ammo-item": "battery", "charges": 150, "container-item": "cell_phone" } ] }, + { + "type": "item_group", + "subtype": "collection", + "id": "charged_smart_phone", + "entries": [ { "item": "smart_phone", "ammo-item": "battery", "charges": 120 } ] + }, { "type": "item_group", "subtype": "collection", @@ -41,6 +47,18 @@ "id": "charged_tazer", "entries": [ { "item": "medium_disposable_cell", "ammo-item": "battery", "charges": 1200, "container-item": "tazer" } ] }, + { + "type": "item_group", + "subtype": "collection", + "id": "charged_ref_lighter", + "entries": [ { "item": "ref_lighter", "charges": 50 } ] + }, + { + "type": "item_group", + "subtype": "collection", + "id": "charged_matches", + "entries": [ { "item": "matches", "charges": 20 } ] + }, { "type": "item_group", "subtype": "collection", @@ -346,10 +364,9 @@ "knit_scarf", "jug_plastic", "can_beans", - "pockknife", - "matches" + "pockknife" ], - "entries": [ { "group": "charged_cell_phone" } ] + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] }, "male": [ "boxer_briefs" ], "female": [ "bra", "panties" ] @@ -397,11 +414,11 @@ "knit_scarf", "backpack", "canteen", - "smart_phone", "wristwatch", "binoculars" ], "entries": [ + { "group": "charged_smart_phone" }, { "item": "crossbow", "ammo-item": "bolt_steel", "charges": 1, "contents-item": "shoulder_strap" }, { "item": "quiver", "contents-group": "quiver_bionic_prepper" }, { "item": "machete", "container-item": "scabbard" } @@ -419,19 +436,8 @@ "points": 0, "items": { "both": { - "items": [ - "jeans", - "longshirt", - "socks", - "coat_winter", - "boots_winter", - "knit_scarf", - "pockknife", - "water_clean", - "matches", - "wristwatch" - ], - "entries": [ { "group": "charged_cell_phone" } ] + "items": [ "jeans", "longshirt", "socks", "coat_winter", "boots_winter", "knit_scarf", "pockknife", "water_clean", "wristwatch" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] @@ -455,8 +461,8 @@ ], "items": { "both": { - "items": [ "pants", "tshirt", "socks", "sweater", "sneakers", "multitool", "water_clean", "matches", "wristwatch" ], - "entries": [ { "group": "charged_cell_phone" } ] + "items": [ "pants", "tshirt", "socks", "sweater", "sneakers", "multitool", "water_clean", "wristwatch" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] @@ -480,11 +486,11 @@ "boots_hiking", "knife_folding", "water_clean", - "matches", "wristwatch" ], "entries": [ { "group": "charged_two_way_radio" }, + { "group": "charged_matches" }, { "item": "ear_plugs", "custom-flags": [ "no_auto_equip" ] }, { "item": "m1911", "ammo-item": "45_acp", "charges": 7, "container-item": "holster" }, { "item": "45_acp", "charges": 23 }, @@ -569,8 +575,11 @@ ], "items": { "both": { - "items": [ "dress_shirt", "pants", "socks", "boots", "coat_lab", "gloves_rubber", "glasses_safety", "smart_phone", "wristwatch" ], - "entries": [ { "item": "medium_battery_cell", "ammo-item": "battery", "charges": 500, "container-item": "chemistry_set" } ] + "items": [ "dress_shirt", "pants", "socks", "boots", "coat_lab", "gloves_rubber", "glasses_safety", "wristwatch" ], + "entries": [ + { "group": "charged_smart_phone" }, + { "item": "medium_battery_cell", "ammo-item": "battery", "charges": 500, "container-item": "chemistry_set" } + ] }, "male": [ "briefs" ], "female": [ "bra", "panties" ] @@ -1062,7 +1071,7 @@ "description": "Cocaine. It is, indeed, a helluva drug. You blew your money on some dust, and before you knew it you were turning tricks behind the local CVS just to score one more line. Where are you going to get your next fix now?", "points": -1, "items": { - "both": [ "crackpipe", "crack", "crack", "ref_lighter", "tank_top" ], + "both": { "items": [ "crackpipe", "crack", "crack", "tank_top" ], "entries": [ { "group": "charged_ref_lighter" } ] }, "male": [ "jeans", "flip_flops" ], "female": [ "jeans", "heels" ] }, @@ -1075,7 +1084,10 @@ "description": "Society drove you to the fringes and left you with no home, no family, no friends. You found solace in the bottom of a bottle. Well, society doesn't mean a thing anymore, and for all the crap thrown your way, you're still standing. God damn, you need a drink.", "points": -1, "items": { - "both": [ "pants", "knit_scarf", "whiskey", "gin", "bum_wine", "ragpouch", "bindle", "can_beans", "pockknife", "matches" ], + "both": { + "items": [ "pants", "knit_scarf", "whiskey", "gin", "bum_wine", "ragpouch", "bindle", "can_beans", "pockknife" ], + "entries": [ { "group": "charged_matches" } ] + }, "male": [ "undershirt" ], "female": [ "camisole" ] }, @@ -1154,18 +1166,8 @@ "pets": [ { "name": "mon_cat", "amount": 30 } ], "items": { "both": { - "items": [ - "jeans", - "longshirt", - "socks", - "coat_winter", - "boots_winter", - "knit_scarf", - "pockknife", - "water_clean", - "matches", - "wristwatch" - ] + "items": [ "jeans", "longshirt", "socks", "coat_winter", "boots_winter", "knit_scarf", "pockknife", "water_clean", "wristwatch" ], + "entries": [ { "group": "charged_matches" } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] @@ -1217,12 +1219,12 @@ "wristwatch", "socks", "dress_shoes", - "cig", - "ref_lighter" + "cig" ], "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_two_way_radio" }, + { "group": "charged_ref_lighter" }, { "item": "sw_619", "ammo-item": "357mag_fmj", "charges": 6, "container-item": "holster" }, { "item": "357mag_fmj", "charges": 24 } ] @@ -1590,8 +1592,11 @@ "skills": [ { "level": 4, "name": "computer" } ], "items": { "both": { - "items": [ "pants", "tshirt_text", "socks", "sneakers", "mbag", "laptop", "smart_phone", "caffeine" ], - "entries": [ { "item": "light_plus_battery_cell", "ammo-item": "battery", "charges": 150, "container-item": "portable_game" } ] + "items": [ "pants", "tshirt_text", "socks", "sneakers", "mbag", "laptop", "caffeine" ], + "entries": [ + { "item": "light_plus_battery_cell", "ammo-item": "battery", "charges": 150, "container-item": "portable_game" }, + { "group": "charged_smart_phone" } + ] }, "male": [ "briefs" ], "female": [ "panties" ] @@ -1673,8 +1678,9 @@ "skills": [ { "level": 1, "name": "gun" }, { "level": 1, "name": "smg" }, { "level": 3, "name": "lockpick" } ], "items": { "both": { - "items": [ "waistcoat", "pants", "dress_shirt", "socks", "dress_shoes", "knit_scarf", "gold_watch", "smart_phone" ], + "items": [ "waistcoat", "pants", "dress_shirt", "socks", "dress_shoes", "knit_scarf", "gold_watch" ], "entries": [ + { "group": "charged_smart_phone" }, { "item": "briefcase_smg", "ammo-item": "9mm", "charges": 30 }, { "item": "mp5mag", "ammo-item": "9mm", "charges": 30 } ] @@ -1785,18 +1791,10 @@ "bio_power_storage_mkII" ], "items": { - "both": [ - "socks", - "tshirt", - "jeans", - "leather_belt", - "boots_steel", - "gloves_work", - "glasses_safety", - "hat_hard", - "smart_phone", - "wristwatch" - ], + "both": { + "items": [ "socks", "tshirt", "jeans", "leather_belt", "boots_steel", "gloves_work", "glasses_safety", "hat_hard", "wristwatch" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "sports_bra", "panties" ] } @@ -1809,18 +1807,20 @@ "points": 5, "CBMs": [ "bio_str_enhancer", "bio_adrenaline", "bio_hydraulics", "bio_metabolics", "bio_power_storage_mkII" ], "items": { - "both": [ - "socks_ankle", - "under_armor_shorts", - "under_armor", - "tshirt", - "shorts", - "lowtops", - "fanny", - "protein_drink", - "smart_phone", - "wristwatch" - ], + "both": { + "items": [ + "socks_ankle", + "under_armor_shorts", + "under_armor", + "tshirt", + "shorts", + "lowtops", + "fanny", + "protein_drink", + "wristwatch" + ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "sports_bra", "panties" ] } @@ -1833,18 +1833,20 @@ "points": 4, "CBMs": [ "bio_adrenaline", "bio_torsionratchet", "bio_power_storage_mkII", "bio_jointservo" ], "items": { - "both": [ - "socks_ankle", - "under_armor_shorts", - "under_armor", - "tshirt", - "shorts", - "lowtops", - "fanny", - "sports_drink", - "smart_phone", - "wristwatch" - ], + "both": { + "items": [ + "socks_ankle", + "under_armor_shorts", + "under_armor", + "tshirt", + "shorts", + "lowtops", + "fanny", + "sports_drink", + "wristwatch" + ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "sports_bra", "panties" ] } @@ -1870,19 +1872,10 @@ "skills": [ { "level": 1, "name": "gun" }, { "level": 1, "name": "pistol" } ], "items": { "both": { - "items": [ - "tac_fullhelmet", - "police_belt", - "pants_cargo", - "under_armor", - "socks", - "boots", - "badge_cybercop", - "smart_phone", - "wristwatch" - ], + "items": [ "tac_fullhelmet", "police_belt", "pants_cargo", "under_armor", "socks", "boots", "badge_cybercop", "wristwatch" ], "entries": [ { "group": "charged_two_way_radio" }, + { "group": "charged_smart_phone" }, { "item": "glock_18c", "ammo-item": "9mmP", "container-item": "holster" }, { "item": "tacvest", "contents-group": "army_mags_glock17" } ] @@ -1933,7 +1926,10 @@ "skills": [ { "level": 2, "name": "barter" }, { "level": 2, "name": "speech" } ], "no_bonus": "teleumbrella", "items": { - "both": [ "socks", "suit", "dress_shoes", "gold_watch", "knit_scarf", "briefcase", "smart_phone", "file", "teleumbrella" ], + "both": { + "items": [ "socks", "suit", "dress_shoes", "gold_watch", "knit_scarf", "briefcase", "file", "teleumbrella" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] } @@ -2076,7 +2072,10 @@ ], "skills": [ { "level": 2, "name": "speech" } ], "items": { - "both": [ "dress_shoes", "socks", "knit_scarf", "suit", "wristwatch", "smart_phone" ], + "both": { + "items": [ "dress_shoes", "socks", "knit_scarf", "suit", "wristwatch" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "bra", "panties" ] } @@ -2100,7 +2099,10 @@ ], "skills": [ { "level": 3, "name": "dodge" } ], "items": { - "both": [ "dress_shoes", "dress_shirt", "knit_scarf", "wristwatch", "blazer", "wristwatch", "smart_phone" ], + "both": { + "items": [ "dress_shoes", "dress_shirt", "knit_scarf", "wristwatch", "blazer", "wristwatch" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs", "socks", "pants" ], "female": [ "bra", "panties", "stockings", "skirt" ] } @@ -2134,9 +2136,9 @@ "both": { "items": [ "suit", "bowhat", "socks", "dress_shoes", "knit_scarf", "cig", "switchblade", "mag_porn", "sunglasses", "shot_00" ], "entries": [ + { "group": "charged_ref_lighter" }, { "item": "glock_19", "ammo-item": "9mm", "container-item": "holster", "charges": 15 }, - { "item": "glockmag", "ammo-item": "9mm", "charges": 15 }, - { "item": "ref_lighter", "charges": 100 } + { "item": "glockmag", "ammo-item": "9mm", "charges": 15 } ] }, "male": [ "boxer_shorts" ], @@ -2176,7 +2178,7 @@ "CBMs": [ "bio_flashlight", "bio_tools", "bio_ups", "bio_watch", "bio_batteries", "bio_power_storage_mkII" ], "skills": [ { "level": 4, "name": "electronics" }, { "level": 2, "name": "fabrication" } ], "items": { - "both": [ "tshirt", "sneakers", "jacket_light", "wristwatch", "smart_phone" ], + "both": { "items": [ "tshirt", "sneakers", "jacket_light", "wristwatch" ], "entries": [ { "group": "charged_smart_phone" } ] }, "male": [ "briefs", "socks", "pants" ], "female": [ "bra", "panties", "stockings", "skirt" ] } @@ -2213,10 +2215,13 @@ "wristwatch", "tobacco", "rolling_paper", - "matches", "backpack" ], - "entries": [ { "group": "charged_cell_phone" }, { "item": "knife_hunting", "container-item": "sheath" } ] + "entries": [ + { "group": "charged_cell_phone" }, + { "group": "charged_matches" }, + { "item": "knife_hunting", "container-item": "sheath" } + ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "boxer_shorts" ] @@ -2260,7 +2265,9 @@ "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.", "points": -1, "flags": [ "NO_BONUS_ITEMS" ], - "items": { "both": [ "bondage_suit", "bondage_mask", "boots", "leather_belt", "matches" ] } + "items": { + "both": { "items": [ "bondage_suit", "bondage_mask", "boots", "leather_belt" ], "entries": [ { "group": "charged_matches" } ] } + } }, { "type": "profession", @@ -2270,8 +2277,8 @@ "points": 0, "items": { "both": { - "items": [ "tobacco", "pipe_tobacco", "ref_lighter", "socks", "dress_shoes", "knit_scarf" ], - "entries": [ { "item": "cane", "custom-flags": [ "auto_wield" ] } ] + "items": [ "tobacco", "pipe_tobacco", "socks", "dress_shoes", "knit_scarf" ], + "entries": [ { "group": "charged_ref_lighter" }, { "item": "cane", "custom-flags": [ "auto_wield" ] } ] }, "male": [ "briefs", "dress_shirt", "pants_checkered", "pocketwatch" ], "female": [ "panties", "bra", "dress", "fanny", "gold_watch" ] @@ -2326,18 +2333,8 @@ "points": 0, "items": { "both": { - "items": [ - "trenchcoat", - "gloves_fingerless", - "socks", - "boots_combat", - "weed", - "tobacco", - "rolling_paper", - "ref_lighter", - "wristwatch" - ], - "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_mp3" } ] + "items": [ "trenchcoat", "gloves_fingerless", "socks", "boots_combat", "weed", "tobacco", "rolling_paper", "wristwatch" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_mp3" }, { "group": "charged_ref_lighter" } ] }, "male": [ "pants_cargo", "tank_top", "boxer_shorts" ], "female": [ "skirt", "corset", "boxer_shorts" ] @@ -2379,19 +2376,8 @@ "points": 0, "items": { "both": { - "items": [ - "dress_shirt", - "tie_skinny", - "sunglasses", - "pants", - "socks", - "dress_shoes", - "rolling_paper", - "tobacco", - "wristwatch", - "ref_lighter" - ], - "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_mp3" } ] + "items": [ "dress_shirt", "tie_skinny", "sunglasses", "pants", "socks", "dress_shoes", "rolling_paper", "tobacco", "wristwatch" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_mp3" }, { "group": "charged_ref_lighter" } ] }, "male": [ "briefs" ], "female": [ "bra", "panties" ] @@ -2474,8 +2460,8 @@ "skills": [ { "level": 2, "name": "chemistry" }, { "level": 2, "name": "firstaid" } ], "items": { "both": { - "items": [ "striped_shirt", "striped_pants", "sneakers", "socks", "adderall", "matches" ], - "entries": [ { "item": "condom", "contents-item": "dayquil" } ] + "items": [ "striped_shirt", "striped_pants", "sneakers", "socks", "adderall" ], + "entries": [ { "item": "condom", "contents-item": "dayquil" }, { "group": "charged_matches" } ] }, "male": [ "briefs" ], "female": [ "bra", "panties" ] @@ -2553,17 +2539,10 @@ "CBMs": [ "bio_razors", "bio_armor_eyes", "bio_sunglasses", "bio_dex_enhancer", "bio_ears", "bio_carbon" ], "skills": [ { "level": 2, "name": "melee" }, { "level": 2, "name": "unarmed" }, { "level": 2, "name": "dodge" } ], "items": { - "both": [ - "socks", - "tank_top", - "jacket_leather", - "pants_leather", - "boots", - "gloves_fingerless", - "smart_phone", - "wristwatch", - "gum" - ], + "both": { + "items": [ "socks", "tank_top", "jacket_leather", "pants_leather", "boots", "gloves_fingerless", "wristwatch", "gum" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "sports_bra", "boy_shorts" ] } @@ -2589,8 +2568,8 @@ "skills": [ { "level": 1, "name": "electronics" }, { "level": 1, "name": "firstaid" }, { "level": 1, "name": "computer" } ], "items": { "both": { - "items": [ "tank_top", "shorts", "socks", "lowtops", "aspirin", "anesthetic_kit", "pockknife", "backpack", "wristwatch" ], - "entries": [ { "group": "charged_cell_phone" } ] + "items": [ "tank_top", "shorts", "socks", "lowtops", "aspirin", "pockknife", "backpack", "wristwatch" ], + "entries": [ { "group": "charged_cell_phone" }, { "item": "anesthetic_kit", "charges": 3000 } ] }, "male": [ "briefs" ], "female": [ "camisole", "panties" ] @@ -2650,19 +2629,21 @@ "points": 1, "skills": [ { "level": 1, "name": "barter" }, { "level": 2, "name": "speech" } ], "items": { - "both": [ - "suit", - "tie_necktie", - "tieclip", - "socks", - "dress_shoes", - "knit_scarf", - "wristwatch", - "smart_phone", - "briefcase", - "money_bundle", - "file" - ], + "both": { + "items": [ + "suit", + "tie_necktie", + "tieclip", + "socks", + "dress_shoes", + "knit_scarf", + "wristwatch", + "briefcase", + "money_bundle", + "file" + ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "bra", "panties" ] } @@ -3160,11 +3141,11 @@ "leather_funnel", "clay_pot", "waterskin", - "needle_bone", "fur_rollmat", "fire_drill" ], "entries": [ + { "item": "needle_bone", "ammo-item": "sinew", "charges": 200 }, { "item": "primitive_knife", "container-item": "sheath" }, { "item": "quiver", "contents-group": "quiver_naturalist" } ] @@ -3221,8 +3202,8 @@ ], "items": { "both": { - "items": [ "stockings", "pockknife", "matches", "pipe_tobacco", "tobacco", "backpack" ], - "entries": [ { "group": "charged_cell_phone" } ] + "items": [ "stockings", "pockknife", "pipe_tobacco", "tobacco", "backpack" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] }, "male": { "items": [ @@ -3245,20 +3226,21 @@ { "item": "lamp_oil", "container-item": "bottle_plastic_small" } ] }, - "female": [ - "dress", - "apron_leather", - "boots", - "gloves_leather", - "long_knit_scarf", - "hat_fur", - "purse", - "oil_lamp", - "needle_wood", - "pot", - "cornmeal", - "salt" - ] + "female": { + "items": [ + "dress", + "apron_leather", + "boots", + "gloves_leather", + "long_knit_scarf", + "hat_fur", + "purse", + "pot", + "cornmeal", + "salt" + ], + "entries": [ { "item": "needle_wood", "ammo-item": "thread", "charges": 200 }, { "item": "oil_lamp", "charges": 750 } ] + } } }, { @@ -3275,23 +3257,24 @@ ], "items": { "both": { - "items": [ "stockings", "pockknife", "matches", "pipe_tobacco", "tobacco", "backpack" ], - "entries": [ { "group": "charged_cell_phone" } ] + "items": [ "stockings", "pockknife", "pipe_tobacco", "tobacco", "backpack" ], + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] + }, + "male": { + "items": [ + "dress", + "apron_leather", + "boots", + "gloves_leather", + "long_knit_scarf", + "hat_fur", + "purse", + "pot", + "cornmeal", + "salt" + ], + "entries": [ { "item": "needle_wood", "ammo-item": "thread", "charges": 200 }, { "item": "oil_lamp", "charges": 750 } ] }, - "male": [ - "dress", - "apron_leather", - "boots", - "gloves_leather", - "long_knit_scarf", - "hat_fur", - "needle_wood", - "purse", - "oil_lamp", - "pot", - "cornmeal", - "salt" - ], "female": { "items": [ "knee_high_boots", @@ -3375,7 +3358,6 @@ "sneakers", "gloves_fingerless", "slingpack", - "matches", "hairpin", "hairpin", "mag_comic", @@ -3384,7 +3366,7 @@ "marble", "slingshot" ], - "entries": [ { "group": "charged_cell_phone" } ] + "entries": [ { "group": "charged_cell_phone" }, { "group": "charged_matches" } ] }, "male": [ "briefs" ], "female": [ "boy_shorts" ] @@ -3434,22 +3416,24 @@ "points": 3, "CBMs": [ "bio_batteries", "bio_power_storage", "bio_int_enhancer", "bio_memory" ], "items": { - "both": [ - "dress_shirt", - "jacket_light", - "pants", - "socks", - "dress_shoes", - "tie_clipon", - "tieclip", - "fancy_sunglasses", - "knit_scarf", - "wristwatch", - "mbag", - "water_mineral", - "smart_phone", - "money_bundle" - ], + "both": { + "items": [ + "dress_shirt", + "jacket_light", + "pants", + "socks", + "dress_shoes", + "tie_clipon", + "tieclip", + "fancy_sunglasses", + "knit_scarf", + "wristwatch", + "mbag", + "water_mineral", + "money_bundle" + ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "panties" ] } @@ -3592,15 +3576,12 @@ "hat_cotton", "knit_scarf", "backpack", - "ref_lighter", "hatchet", "e_tool", "tent_kit", "rollmat", "sleeping_bag_roll", "knife_swissarmy", - "gasoline_lantern", - "canteen", "granola", "pur_tablets", "wristwatch", @@ -3608,6 +3589,9 @@ ], "entries": [ { "group": "charged_cell_phone" }, + { "group": "charged_ref_lighter" }, + { "item": "gasoline_lantern", "charges": 500 }, + { "item": "water_clean", "ammo-item": "water_clean", "container-item": "canteen" }, { "item": "medium_battery_cell", "ammo-item": "battery", "charges": 500, "container-item": "mess_kit" } ] }, @@ -3634,10 +3618,10 @@ "e_tool", "tool_belt", "mbag", - "wristwatch", - "matches" + "wristwatch" ], "entries": [ + { "group": "charged_matches" }, { "item": "ear_plugs", "custom-flags": [ "no_auto_equip" ] }, { "item": "jackhammer", "charges": 400 }, { "item": "light_minus_disposable_cell", "charges": 100 }, @@ -3667,10 +3651,10 @@ "mbag", "briefcase", "wristwatch", - "hat_hard", - "matches" + "hat_hard" ], "entries": [ + { "group": "charged_matches" }, { "item": "ear_plugs", "custom-flags": [ "no_auto_equip" ] }, { "item": "dynamite", "count": 8 }, { "item": "dynamite", "count": 4 }, @@ -3752,12 +3736,11 @@ "dress_shoes", "coat_lab", "bandages", - "anesthetic_kit", "1st_aid", "wristwatch", "stethoscope" ], - "entries": [ { "group": "charged_cell_phone" } ] + "entries": [ { "group": "charged_cell_phone" }, { "item": "anesthetic_kit", "charges": 3000 } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] @@ -3799,7 +3782,10 @@ { "level": 1, "name": "throw" } ], "items": { - "both": [ "jeans", "polo_shirt", "socks", "dress_shoes", "mbag", "caffeine", "smart_phone", "wristwatch" ], + "both": { + "items": [ "jeans", "polo_shirt", "socks", "dress_shoes", "mbag", "caffeine", "wristwatch" ], + "entries": [ { "group": "charged_smart_phone" } ] + }, "male": [ "briefs" ], "female": [ "bra", "panties" ] } @@ -3882,10 +3868,9 @@ "antibiotics", "oxycodone", "1st_aid", - "smart_phone", "wristwatch" ], - "entries": [ { "item": "medium_battery_cell", "charges": 500 } ] + "entries": [ { "group": "charged_smart_phone" }, { "item": "medium_battery_cell", "charges": 500 } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] @@ -3941,19 +3926,10 @@ "skills": [ { "level": 4, "name": "barter" }, { "level": 6, "name": "speech" } ], "traits": [ "LIAR" ], "items": { - "both": [ - "suit", - "tieclip", - "socks_wool", - "dress_shoes", - "smart_phone", - "gold_watch", - "briefcase", - "tie_skinny", - "file", - "ref_lighter", - "cigar" - ], + "both": { + "items": [ "suit", "tieclip", "socks_wool", "dress_shoes", "gold_watch", "briefcase", "tie_skinny", "file", "cigar" ], + "entries": [ { "group": "charged_ref_lighter" }, { "group": "charged_smart_phone" } ] + }, "male": [ "boxer_shorts" ], "female": [ "bra", "panties" ] } @@ -4001,19 +3977,8 @@ "both": { "ammo": 100, "magazine": 100, - "items": [ - "tshirt_tour", - "jeans", - "socks", - "boots_steel", - "multitool", - "wristwatch", - "gloves_work", - "mbag", - "soldering_iron", - "matches" - ], - "entries": [ { "group": "charged_cell_phone" }, { "item": "jacket_jean" } ] + "items": [ "tshirt_tour", "jeans", "socks", "boots_steel", "multitool", "wristwatch", "gloves_work", "mbag", "soldering_iron" ], + "entries": [ { "group": "charged_cell_phone" }, { "item": "jacket_jean" }, { "group": "charged_matches" } ] }, "male": [ "boxer_shorts" ], "female": [ "bra", "boy_shorts" ] @@ -4108,7 +4073,10 @@ "skills": [ { "level": 1, "name": "speech" }, { "level": 2, "name": "driving" } ], "vehicle": "car_sports", "items": { - "both": { "items": [ "gold_watch", "water_mineral", "smart_phone", "money_bundle", "cig", "ref_lighter" ] }, + "both": { + "items": [ "gold_watch", "water_mineral", "money_bundle", "cig" ], + "entries": [ { "group": "charged_ref_lighter" }, { "group": "charged_smart_phone" } ] + }, "male": [ "boxer_shorts", "pants", "dress_shoes", "polo_shirt", "socks" ], "female": [ "tank_top", "bra", "panties", "skirt", "heels", "jacket_leather", "stockings" ] } From 909133dd297514af4d6e36883f8f66cc67701a50 Mon Sep 17 00:00:00 2001 From: nexusmrsep <39925111+nexusmrsep@users.noreply.github.com> Date: Tue, 30 Jun 2020 09:10:15 +0200 Subject: [PATCH 34/41] Fire extinguishers use visible fields (#41639) --- data/json/emit.json | 7 +++ data/json/field_type.json | 87 ++++++++++++++++++++++++++ data/json/item_actions.json | 5 -- data/json/items/ammo.json | 17 +++++ data/json/items/ammo_types.json | 6 ++ data/json/items/tool/firefighting.json | 58 +++++++++++++++-- src/field_type.cpp | 2 + src/field_type.h | 1 + src/item_factory.cpp | 1 - src/iuse.cpp | 24 +------ src/iuse.h | 1 - src/map_field.cpp | 9 +++ 12 files changed, 184 insertions(+), 34 deletions(-) diff --git a/data/json/emit.json b/data/json/emit.json index 4c9045aef0390..f0053ab79d09e 100644 --- a/data/json/emit.json +++ b/data/json/emit.json @@ -331,5 +331,12 @@ "field": "fd_fog", "intensity": 2, "qty": 200 + }, + { + "id": "emit_extinguisher_burst", + "type": "emit", + "field": "fd_extinguisher", + "intensity": 1, + "qty": 10 } ] diff --git a/data/json/field_type.json b/data/json/field_type.json index 2d0e71aced560..76f8b860bb0c5 100644 --- a/data/json/field_type.json +++ b/data/json/field_type.json @@ -239,6 +239,93 @@ "display_items": false, "display_field": true }, + { + "id": "fd_extinguisher", + "type": "field_type", + "intensity_levels": [ + { + "name": "extinguisher mist", + "sym": "%", + "color": "white", + "dangerous": true, + "translucency": 0.1, + "convection_temperature_mod": -10, + "effects": [ + { + "effect_id": "poison", + "body_part": "MOUTH", + "intensity": 2, + "min_duration": "2 minutes", + "max_duration": "2 minutes", + "immune_inside_vehicle": true, + "message": "You feel sick from inhaling the extinguisher mist", + "message_type": "bad" + } + ] + }, + { + "name": "extinguisher cloud", + "color": "white", + "convection_temperature_mod": -20, + "translucency": 0.4, + "effects": [ + { + "effect_id": "poison", + "body_part": "MOUTH", + "intensity": 2, + "min_duration": "2 minutes", + "max_duration": "2 minutes", + "immune_inside_vehicle": true, + "message": "You feel sick from inhaling the extinguisher cloud", + "message_type": "bad" + } + ] + }, + { + "name": "thick extinguisher cloud", + "color": "white", + "convection_temperature_mod": -30, + "translucency": 0.7, + "effects": [ + { + "effect_id": "poison", + "body_part": "MOUTH", + "intensity": 5, + "min_duration": "3 minutes", + "max_duration": "3 minutes", + "//": "won't be applied outside of vehicles, so it could apply harsher effect", + "immune_outside_vehicle": true, + "message": "You feel sick from inhaling the thick extinguisher cloud", + "message_type": "bad" + }, + { + "effect_id": "badpoison", + "body_part": "MOUTH", + "intensity": 5, + "min_duration": "3 minutes", + "max_duration": "3 minutes", + "//": "won't be applied inside of vehicles, so it could apply lesser effect", + "immune_inside_vehicle": true, + "message": "You feel sick from inhaling the thick extinguisher cloud", + "message_type": "bad" + } + ] + } + ], + "description_affix": "on", + "decay_amount_factor": 3, + "priority": 4, + "half_life": "10 seconds", + "phase": "gas", + "display_items": false, + "display_field": true, + "looks_like": "fd_fog", + "gas_absorption_factor": 15, + "has_fume": true, + "percent_spread": 90, + "dirty_transparency_cache": true, + "immunity_data": { "body_part_env_resistance": [ [ "MOUTH", 15 ] ] } + }, { "id": "fd_rubble", "type": "field_type", diff --git a/data/json/item_actions.json b/data/json/item_actions.json index 676f98f7f623d..9f9e62a47d45c 100644 --- a/data/json/item_actions.json +++ b/data/json/item_actions.json @@ -894,11 +894,6 @@ "id": "THORAZINE", "name": { "str": "Take" } }, - { - "type": "item_action", - "id": "THROWABLE_EXTINGUISHER_ACT", - "name": { "str": "Extinguish a fire" } - }, { "type": "item_action", "id": "TOWEL", diff --git a/data/json/items/ammo.json b/data/json/items/ammo.json index 45f6ad2ea0a03..a4f7924cc0974 100644 --- a/data/json/items/ammo.json +++ b/data/json/items/ammo.json @@ -1127,6 +1127,23 @@ "phase": "gas", "ammo_type": "nitrox" }, + { + "type": "AMMO", + "id": "extinguishing_agent", + "category": "chems", + "price": 500, + "price_postapoc": 250, + "name": { "str_sp": "extinguishing agent" }, + "symbol": "%", + "color": "white", + "container": "bottle_plastic", + "description": "Dry chemical solution effective in extinguishing fires.", + "volume": "250 ml", + "weight": "1 g", + "phase": "gas", + "ammo_type": "extinguishing_agent", + "count": 10 + }, { "id": "tinder", "type": "AMMO", diff --git a/data/json/items/ammo_types.json b/data/json/items/ammo_types.json index 58ea87677cfcc..6595a78270ca2 100644 --- a/data/json/items/ammo_types.json +++ b/data/json/items/ammo_types.json @@ -629,6 +629,12 @@ "name": "compressed air", "default": "nitrox" }, + { + "type": "ammunition_type", + "id": "extinguishing_agent", + "name": "extinguishing agent", + "default": "extinguishing_agent" + }, { "id": "tinder", "name": "tinder", diff --git a/data/json/items/tool/firefighting.json b/data/json/items/tool/firefighting.json index 71a47c8c9a441..d7d4dd8b44ed2 100644 --- a/data/json/items/tool/firefighting.json +++ b/data/json/items/tool/firefighting.json @@ -35,8 +35,18 @@ "symbol": ";", "color": "red", "initial_charges": 100, + "pocket_data": [ + { + "pocket_type": "MAGAZINE", + "airtight": true, + "watertight": true, + "rigid": true, + "ammo_restriction": { "extinguishing_agent": 100 } + } + ], "max_charges": 100, "charges_per_use": 1, + "flags": [ "NO_UNLOAD", "NO_RELOAD" ], "use_action": [ "EXTINGUISHER" ] }, { @@ -91,9 +101,20 @@ "material": [ "steel", "plastic" ], "symbol": ";", "color": "red", + "pocket_data": [ + { + "pocket_type": "MAGAZINE", + "airtight": true, + "watertight": true, + "rigid": true, + "ammo_restriction": { "extinguishing_agent": 10 } + } + ], "initial_charges": 10, "max_charges": 10, + "ammo": "extinguishing_agent", "charges_per_use": 1, + "flags": [ "NO_UNLOAD", "NO_RELOAD" ], "use_action": [ "EXTINGUISHER" ] }, { @@ -101,18 +122,47 @@ "type": "TOOL", "category": "tools", "name": { "str": "throwable fire extinguisher" }, - "description": "This is a fire extinguisher in grenade form. While not as effective as a regular fire extinguisher, you can use it from a distance. It is activated by heat, so just throw it into the flames.", + "description": "This is a fire extinguisher in grenade form. While not as effective as a regular fire extinguisher, you can use it from a distance. It has a plastic plug that can be pulled, but is primarely activated by heat, so just throw it into the flames.", "weight": "630 g", "volume": "250 ml", "price": 3000, "price_postapoc": 50, "to_hit": -1, "bashing": 3, - "material": [ "plastic" ], + "material": [ "steel" ], "symbol": "*", "color": "blue", - "use_action": [ "THROWABLE_EXTINGUISHER_ACT" ], - "flags": [ "ACT_IN_FIRE" ] + "use_action": { + "target": "throw_extinguisher_act", + "target_charges": 3, + "menu_text": "Pull plug", + "msg": "You pull the plug on the extinguisher grenade.", + "active": true, + "type": "transform" + }, + "flags": [ "ACT_IN_FIRE", "BOMB" ] + }, + { + "id": "throw_extinguisher_act", + "type": "TOOL", + "category": "tools", + "name": { "str": "active throwable fire extinguisher" }, + "description": "This is an active extinguisher grenade, likely to burst any second now. Better throw it!", + "weight": "630 g", + "volume": "250 ml", + "price": 0, + "price_postapoc": 0, + "to_hit": -1, + "bashing": 6, + "material": [ "steel" ], + "symbol": "*", + "color": "light_red", + "initial_charges": 3, + "max_charges": 3, + "turns_per_charge": 1, + "emits": [ "emit_extinguisher_burst" ], + "revert_to": "canister_empty", + "flags": [ "TRADER_AVOID" ] }, { "id": "pike_pole", diff --git a/src/field_type.cpp b/src/field_type.cpp index c08adb314a043..d6ae14b553938 100644 --- a/src/field_type.cpp +++ b/src/field_type.cpp @@ -316,6 +316,7 @@ const std::vector &field_types::get_all() field_type_id fd_null, fd_blood, fd_bile, + fd_extinguisher, fd_gibs_flesh, fd_gibs_veggy, fd_web, @@ -373,6 +374,7 @@ void field_types::set_field_type_ids() fd_null = field_type_id( "fd_null" ); fd_blood = field_type_id( "fd_blood" ); fd_bile = field_type_id( "fd_bile" ); + fd_extinguisher = field_type_id( "fd_extinguisher" ); fd_gibs_flesh = field_type_id( "fd_gibs_flesh" ); fd_gibs_veggy = field_type_id( "fd_gibs_veggy" ); fd_web = field_type_id( "fd_web" ); diff --git a/src/field_type.h b/src/field_type.h index a83ef1b17428a..d306a5d155963 100644 --- a/src/field_type.h +++ b/src/field_type.h @@ -268,6 +268,7 @@ field_type get_field_type_by_legacy_enum( int legacy_enum_id ); extern field_type_id fd_null, fd_blood, fd_bile, + fd_extinguisher, fd_gibs_flesh, fd_gibs_veggy, fd_web, diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 11817d3f48187..db6bd5e985921 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -963,7 +963,6 @@ void Item_factory::init() add_iuse( "TAZER2", &iuse::tazer2 ); add_iuse( "TELEPORT", &iuse::teleport ); add_iuse( "THORAZINE", &iuse::thorazine ); - add_iuse( "THROWABLE_EXTINGUISHER_ACT", &iuse::throwable_extinguisher_act ); add_iuse( "TOWEL", &iuse::towel ); add_iuse( "TRIMMER_OFF", &iuse::trimmer_off ); add_iuse( "TRIMMER_ON", &iuse::trimmer_on ); diff --git a/src/iuse.cpp b/src/iuse.cpp index 0dc3d385717b3..4fae904d301d5 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -2012,7 +2012,7 @@ int iuse::extinguisher( player *p, item *it, bool, const tripoint & ) p->moves -= to_moves( 2_seconds ); // Reduce the strength of fire (if any) in the target tile. - g->m.mod_field_intensity( dest, fd_fire, 0 - rng( 2, 3 ) ); + g->m.add_field( dest, fd_extinguisher, 3, 10_turns ); // Also spray monsters in that tile. if( monster *const mon_ptr = g->critter_at( dest, true ) ) { @@ -3667,28 +3667,6 @@ int iuse::can_goo( player *p, item *it, bool, const tripoint & ) return it->type->charges_to_use(); } -int iuse::throwable_extinguisher_act( player *, item *it, bool, const tripoint &pos ) -{ - if( pos.x == -999 || pos.y == -999 ) { - return 0; - } - if( g->m.get_field( pos, fd_fire ) != nullptr ) { - sounds::sound( pos, 50, sounds::sound_t::combat, _( "Bang!" ), false, "explosion", "small" ); - // Reduce the strength of fire (if any) in the target tile. - g->m.mod_field_intensity( pos, fd_fire, 0 - 2 ); - // Slightly reduce the strength of fire around and in the target tile. - for( const tripoint &dest : g->m.points_in_radius( pos, 1 ) ) { - if( g->m.passable( dest ) && dest != pos ) { - g->m.mod_field_intensity( dest, fd_fire, 0 - rng( 0, 2 ) ); - } - } - it->charges = -1; - return 1; - } - it->active = false; - return 0; -} - int iuse::granade( player *p, item *it, bool, const tripoint & ) { p->add_msg_if_player( _( "You pull the pin on the Granade." ) ); diff --git a/src/iuse.h b/src/iuse.h index 55bb787b31df7..6de160f2a237e 100644 --- a/src/iuse.h +++ b/src/iuse.h @@ -188,7 +188,6 @@ int talking_doll( player *, item *, bool, const tripoint & ); int tazer( player *, item *, bool, const tripoint & ); int tazer2( player *, item *, bool, const tripoint & ); int teleport( player *, item *, bool, const tripoint & ); -int throwable_extinguisher_act( player *, item *, bool, const tripoint & ); int toolmod_attach( player *, item *, bool, const tripoint & ); int tow_attach( player *, item *, bool, const tripoint & ); int towel( player *, item *, bool, const tripoint & ); diff --git a/src/map_field.cpp b/src/map_field.cpp index c0c7b22bc8085..f49f38586b05b 100644 --- a/src/map_field.cpp +++ b/src/map_field.cpp @@ -488,6 +488,15 @@ bool map::process_fields_in_submap( submap *const current_submap, } // TODO: Allow spreading to the sides if age < 0 && intensity == 3 } + + if( curtype == fd_extinguisher ) { + field_entry *fire_here = maptile_at_internal( p ).find_field( fd_fire ); + if( fire_here != nullptr ) { + // extinguisher fights fire in 1:1 ratio + fire_here->set_field_intensity( fire_here->get_field_intensity() - cur.get_field_intensity() ); + cur.set_field_intensity( cur.get_field_intensity() - fire_here->get_field_intensity() ); + } + } if( curtype.obj().apply_slime_factor > 0 ) { sblk.apply_slime( p, cur.get_field_intensity() * curtype.obj().apply_slime_factor ); } From bbbf1ff622fef4de57888ce47126889a0d4c0761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jianxiang=20Wang=20=28=E7=8E=8B=E5=81=A5=E7=BF=94=29?= Date: Tue, 30 Jun 2020 15:12:35 +0800 Subject: [PATCH 35/41] Fix some crashes and item disappearance (#41630) * Fix crash when trading if an item has zero charges * Fix std::bad_alloc or segfault when loading save for a second time * Fix item disappearing when picking item up with full inventory and hands and canceling the wielding prompt. * Fix content disappearing when unloading item * Disallow wielding item unloaded from currently wielded item to avoid crash * Fix crash when trying to wield item from wielded container * Astyle * Fix wrong message shown when unwielding wielded item --- src/character.cpp | 41 +++++++++++++++-------------------------- src/character.h | 12 +++--------- src/game.cpp | 12 ++++-------- src/item_pocket.cpp | 4 +++- src/npctrade.cpp | 15 ++++++++++++--- src/pickup.cpp | 31 ++++++++++++++++--------------- src/player.cpp | 25 +++++++++++++++++-------- 7 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 3f4a2c628cfa6..d04adcca5d0e3 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -2284,28 +2284,12 @@ std::vector Character::nearby( const return res; } -int Character::i_add_to_container( const item &it, const bool unloading ) -{ - int charges = it.count(); - if( unloading || !it.count_by_charges() ) { - return charges; - } - - charges -= weapon.fill_with( *it.type, charges ); - for( item &worn_it : worn ) { - if( charges > 0 ) { - charges -= worn_it.fill_with( *it.type, charges ); - } else { - break; - } - } - - return charges; -} - item_pocket *Character::best_pocket( const item &it, const item *avoid ) { - item_pocket *ret = weapon.best_pocket( it ); + item_pocket *ret = nullptr; + if( &weapon != avoid ) { + ret = weapon.best_pocket( it ); + } for( item &worn_it : worn ) { if( &worn_it == avoid ) { continue; @@ -2324,7 +2308,7 @@ item_pocket *Character::best_pocket( const item &it, const item *avoid ) return ret; } -item *Character::try_add( item it, const item *avoid ) +item *Character::try_add( item it, const item *avoid, const bool allow_wield ) { itype_id item_type_id = it.typeId(); last_item = item_type_id; @@ -2355,7 +2339,7 @@ item *Character::try_add( item it, const item *avoid ) return nullptr; } } else { - if( wield( it ) ) { + if( allow_wield && wield( it ) ) { ret = &weapon; } else { return nullptr; @@ -2374,12 +2358,17 @@ item *Character::try_add( item it, const item *avoid ) return ret; } -item &Character::i_add( item it, bool /* should_stack */, const item *avoid ) +item &Character::i_add( item it, bool /* should_stack */, const item *avoid, const bool allow_drop, + const bool allow_wield ) { - item *added = try_add( it, avoid ); + item *added = try_add( it, avoid, /*allow_wield=*/allow_wield ); if( added == nullptr ) { - if( !wield( it ) ) { - return get_map().add_item_or_charges( pos(), it ); + if( !allow_wield || !wield( it ) ) { + if( allow_drop ) { + return get_map().add_item_or_charges( pos(), it ); + } else { + return null_item_reference(); + } } else { return weapon; } diff --git a/src/character.h b/src/character.h index d58d31a355c25..523ef41f86594 100644 --- a/src/character.h +++ b/src/character.h @@ -1346,20 +1346,14 @@ class Character : public Creature, public visitable item &used_weapon(); /*@}*/ - /** - * Try to find containers that can contain @it and fills them up as much as possible. - * Does not work for items that are not count by charges. - * @param unloading Do not try to add to a container when the item was intentionally unloaded. - * @return Remaining charges which could not be stored on the character. - */ - int i_add_to_container( const item &it, bool unloading ); /** * Adds the item to the character's worn items or wields it, or prompts if the Character cannot pick it up. * @avoid is the item to not put @it into */ - item &i_add( item it, bool should_stack = true, const item *avoid = nullptr ); + item &i_add( item it, bool should_stack = true, const item *avoid = nullptr, bool allow_drop = true, + bool allow_wield = true ); /** tries to add to the character's inventory without a popup. returns nullptr if it fails. */ - item *try_add( item it, const item *avoid = nullptr ); + item *try_add( item it, const item *avoid = nullptr, bool allow_wield = true ); /** * Try to pour the given liquid into the given container/vehicle. The transferred charges are diff --git a/src/game.cpp b/src/game.cpp index 3cdea2d048f75..16ddae9681fd8 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -8972,6 +8972,10 @@ void game::wield( item_location loc ) debugmsg( "ERROR: tried to wield null item" ); return; } + if( &u.weapon != &*loc && u.weapon.has_item( *loc ) ) { + add_msg( m_info, _( "You need to put the bag away before trying to wield something from it." ) ); + return; + } if( u.is_armed() ) { const bool is_unwielding = u.is_wielding( *loc ); const auto ret = u.can_unwield( *loc ); @@ -8991,14 +8995,6 @@ void game::wield( item_location loc ) return; } } - if( !loc ) { - /** - * If we lost the location here, that means the thing we're - * trying to wield was inside a wielded item. - */ - add_msg( m_info, "You need to put the bag away before trying to wield something from it." ); - return; - } const auto ret = u.can_wield( *loc ); if( !ret.success() ) { diff --git a/src/item_pocket.cpp b/src/item_pocket.cpp index 9312acb413b03..af3f0d59c0f7a 100644 --- a/src/item_pocket.cpp +++ b/src/item_pocket.cpp @@ -251,7 +251,9 @@ bool item_pocket::stacks_with( const item_pocket &rhs ) const bool item_pocket::is_funnel_container( units::volume &bigger_than ) const { - static const std::vector allowed_liquids{ + // should not be static, since after reloading some members of the item objects, + // such as item types, may be invalidated. + const std::vector allowed_liquids{ item( "water", calendar::turn_zero, 1 ), item( "water_acid", calendar::turn_zero, 1 ), item( "water_acid_weak", calendar::turn_zero, 1 ) diff --git a/src/npctrade.cpp b/src/npctrade.cpp index 6e5cf4312193f..95195e851b19d 100644 --- a/src/npctrade.cpp +++ b/src/npctrade.cpp @@ -163,6 +163,11 @@ std::vector npc_trading::init_buying( player &buyer, player &selle return; } + if( it.count() <= 0 ) { + debugmsg( "item %s has zero or negative charges", it.typeId().str() ); + return; + } + const int market_price = it.price( true ); int val = np.value( it, market_price ); if( ( is_npc && np.wants_to_sell( it, val, market_price ) ) || @@ -212,9 +217,13 @@ void item_pricing::set_values( int ip_count ) count = ip_count; } else { charges = i_p->count(); - price /= charges; - vol /= charges; - weight /= charges; + if( charges > 0 ) { + price /= charges; + vol /= charges; + weight /= charges; + } else { + debugmsg( "item %s has zero or negative charges", i_p->typeId().str() ); + } } } diff --git a/src/pickup.cpp b/src/pickup.cpp index bd0dbd602e57e..c143686030031 100644 --- a/src/pickup.cpp +++ b/src/pickup.cpp @@ -262,16 +262,7 @@ bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &offer } bool did_prompt = false; - if( newit.count_by_charges() ) { - newit.charges -= u.i_add( newit ).charges; - // if the item stacks with another item when added, - // the charges returned may be larger than the charges of the item added. - newit.charges = std::max( 0, newit.charges ); - } - if( newit.is_ammo() && newit.charges <= 0 ) { - picked_up = true; - option = NUM_ANSWERS; //Skip the options part - } else if( newit.is_frozen_liquid() ) { + if( newit.is_frozen_liquid() ) { if( !( got_water = !( u.crush_frozen_liquid( newloc ) ) ) ) { option = STASH; } @@ -346,12 +337,22 @@ bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &offer break; } // Intentional fallthrough - case STASH: - auto &entry = mapPickup[newit.tname()]; - entry.second += newit.count(); - entry.first = u.i_add( newit ); - picked_up = true; + case STASH: { + item &added_it = u.i_add( newit, true, nullptr, /*allow_drop=*/false ); + if( added_it.is_null() ) { + // failed to add, do nothing + } else if( &added_it == &it ) { + // merged to the original stack, restore original charges + it.charges -= newit.charges; + } else { + // successfully added + auto &entry = mapPickup[newit.tname()]; + entry.second += newit.count(); + entry.first = added_it; + picked_up = true; + } break; + } } if( picked_up ) { diff --git a/src/player.cpp b/src/player.cpp index 0cd7bc9e53cfb..1a5a371a95960 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -2801,23 +2801,32 @@ bool player::takeoff( int pos ) return takeoff( i_at( pos ) ); } -bool player::add_or_drop_with_msg( item &it, const bool unloading, const item *avoid ) +bool player::add_or_drop_with_msg( item &it, const bool /*unloading*/, const item *avoid ) { if( it.made_of( phase_id::LIQUID ) ) { liquid_handler::consume_liquid( it, 1 ); return it.charges <= 0; } - it.charges = this->i_add_to_container( it, unloading ); - if( it.is_ammo() && it.charges == 0 ) { - return true; - } else if( !this->can_pickVolume( it ) ) { + if( !this->can_pickVolume( it ) ) { put_into_vehicle_or_drop( *this, item_drop_reason::too_large, { it } ); } else if( !this->can_pickWeight( it, !get_option( "DANGEROUS_PICKUPS" ) ) ) { put_into_vehicle_or_drop( *this, item_drop_reason::too_heavy, { it } ); } else { - auto &ni = this->i_add( it, true, avoid ); - add_msg( _( "You put the %s in your inventory." ), ni.tname() ); - add_msg( m_info, "%c - %s", ni.invlet == 0 ? ' ' : ni.invlet, ni.tname() ); + const bool allow_wield = !weapon.has_item( it ); + const int prev_charges = it.charges; + auto &ni = this->i_add( it, true, avoid, /*allow_drop=*/false, /*allow_wield=*/allow_wield ); + if( ni.is_null() ) { + // failed to add + put_into_vehicle_or_drop( *this, item_drop_reason::tumbling, { it } ); + } else if( &ni == &it ) { + // merged into the original stack, restore original charges + it.charges = prev_charges; + put_into_vehicle_or_drop( *this, item_drop_reason::tumbling, { it } ); + } else { + // successfully added + add_msg( _( "You put the %s in your inventory." ), ni.tname() ); + add_msg( m_info, "%c - %s", ni.invlet == 0 ? ' ' : ni.invlet, ni.tname() ); + } } return true; } From 582d6449d6dd1971091346dedfe4c08dca19dadd Mon Sep 17 00:00:00 2001 From: LaVeyanFiend <51099123+LaVeyanFiend@users.noreply.github.com> Date: Tue, 30 Jun 2020 03:13:21 -0400 Subject: [PATCH 36/41] Gun volume audit for 9x19, part 1 (#41596) --- data/json/items/armor/storage.json | 8 ++-- data/json/items/gun/9mm.json | 72 +++++++++++++++--------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/data/json/items/armor/storage.json b/data/json/items/armor/storage.json index 9065d3482c926..836b8a59c04ad 100644 --- a/data/json/items/armor/storage.json +++ b/data/json/items/armor/storage.json @@ -686,21 +686,23 @@ "type": "ARMOR", "copy-from": "briefcase", "looks_like": "briefcase", + "weight": "1500 g", + "volume": "15232 ml", + "longest_side": "544 mm", "name": { "str": "H&K operational briefcase (empty)", "str_pl": "H&K operational briefcases (empty)" }, "description": "This is a plain, hard-sided black briefcase with a trigger in the handle and a concealed hole in the side. Squeezing the trigger would currently do nothing, as it is empty. Don't forget to put a suitable MP5 back inside before you try to pay any ransom fees with lead.", "pocket_data": [ { "pocket_type": "CONTAINER", "rigid": true, - "max_contains_volume": "14500 ml", + "max_contains_volume": "14 L", "max_contains_weight": "30 kg", "max_item_length": "50 cm", "moves": 300 } ], "price": 2000, - "price_postapoc": 1250, - "weight": "950 g" + "price_postapoc": 1250 }, { "id": "jerrypack", diff --git a/data/json/items/gun/9mm.json b/data/json/items/gun/9mm.json index c874e1e8b3417..6c5fa335940cc 100644 --- a/data/json/items/gun/9mm.json +++ b/data/json/items/gun/9mm.json @@ -7,7 +7,8 @@ "name": { "str": "Beretta 90-two" }, "description": "A more modern version of Beretta's popular 92 series of handguns, the 90-two performs largely the same. The main difference is a sleeker, almost futuristic-looking design owed in large parts to the polymer underbarrel rail cover.", "weight": "921 g", - "volume": "518 ml", + "volume": "554 ml", + "longest_side": "250 mm", "price": 65000, "to_hit": -2, "bashing": 8, @@ -86,8 +87,9 @@ "reload_noise_volume": 10, "name": { "str": "Cx4 Storm" }, "description": "A small pistol caliber carbine designed for police use and civilian self-defense, the Cx4 Storm uses magazines that are interchangeable with other Beretta 9x19mm handguns.", - "weight": "2580 g", - "volume": "1500 ml", + "weight": "2575 g", + "volume": "4458 ml", + "longest_side": "762 mm", "price": 90000, "price_postapoc": 4000, "to_hit": -1, @@ -136,7 +138,8 @@ "name": { "str": "Glock 19" }, "description": "Possibly the most popular pistol in existence. The Glock 19 is often derided for its plastic construction, but it is easy to shoot.", "weight": "600 g", - "volume": "500 ml", + "volume": "386 ml", + "longest_side": "211 mm", "price": 69000, "price_postapoc": 2500, "to_hit": -2, @@ -168,8 +171,9 @@ "reload_noise_volume": 10, "name": { "str": "H&K MP5A2" }, "description": "The Heckler & Koch MP5 is one of the most widely-used submachine guns in the world, and has been adopted by special police forces and militaries alike. Its high degree of accuracy and low recoil are universally praised.", - "weight": "2730 g", - "volume": "2894 ml", + "weight": "2726 g", + "volume": "3932 ml", + "longest_side": "682 mm", "price": 280000, "price_postapoc": 3500, "to_hit": -2, @@ -217,22 +221,10 @@ "name": { "str": "H&K MP5SD" }, "description": "The H&K MP5SD offers subsonic performance in almost the same footprint as the H&K MP5, retaining its handiness. The large suppressor cuts down on muzzle flash greatly, aiding in night operations. It has also seen some popularity with SWAT teams, as it lowers the risk of fire and explosions in illegal laboratories. With body armor in more common use, the MP5SD has waned in popularity among special forces due to its decreased terminal performance.", "weight": "3230 g", + "volume": "3499 ml", + "longest_side": "666 mm", "price": 3000000, "price_postapoc": 14000, - "valid_mod_locations": [ - [ "accessories", 3 ], - [ "barrel", 1 ], - [ "bore", 1 ], - [ "brass catcher", 1 ], - [ "grip", 1 ], - [ "mechanism", 4 ], - [ "rail mount", 1 ], - [ "sights mount", 1 ], - [ "underbarrel mount", 1 ], - [ "sling", 1 ], - [ "stock", 1 ] - ], - "modes": [ [ "DEFAULT", "semi-auto", 1 ], [ "BURST", "3 rd.", 3 ], [ "AUTO", "auto", 4 ] ], "built_in_mods": [ "mp5sd_suppressor" ] }, { @@ -241,8 +233,10 @@ "copy-from": "hk_mp5", "name": { "str": "H&K MP5K-PDW" }, "description": "The Heckler & Koch MP5 is one of the most widely-used submachine guns in the world, and has been adopted by special police forces and militaries alike. Its high degree of accuracy and low recoil are universally praised. The MP5K-PDW model features a shorter barrel, a built-in foregrip, and a side folding stock for vehicle or aircraft crew use.", - "weight": "2360 g", - "volume": "1753 ml", + "weight": "2292 g", + "volume": "2601 ml", + "//": "Forward grip's 68g & 119ml deducted", + "longest_side": "377 mm", "price_postapoc": 3500, "bashing": 8, "dispersion": 270, @@ -269,8 +263,10 @@ "copy-from": "hk_mp5", "name": { "str": "PTR 603" }, "description": "The PTR 603 is a semi-automatic copy of the famous MP5 series, domestically produced for the US market on original Heckler and Koch tooling by PTR Industries. Like the MP5, its roller delayed blowback action offers smooth shooting and precision, setting it apart from other submachine guns and pistol caliber carbines. This model is configured as a pistol to avoid inconvenient and costly NFA regulations. A welded on section of M1913 rail offers convenient mounting for aftermarket optics, but precludes the use of claw mounts.", - "relative": { "weight": -550, "volume": "-500 ml", "handling_modifier": -6 }, - "//": "Attach a pistol stock and you get a semi MP5 again.", + "weight": "2177 g", + "volume": "2110 ml", + "longest_side": "377 mm", + "skill": "pistol", "modes": [ [ "DEFAULT", "semi-auto", 1 ] ], "bashing": 7, "dispersion": 270, @@ -293,11 +289,13 @@ { "id": "briefcase_smg", "copy-from": "hk_mp5k", + "looks_like": "hk_briefcase", "type": "GUN", "name": { "str": "H&K operational briefcase" }, "description": "This is a hard-sided briefcase with a trigger in the handle and a concealed hole in the side. To fire the internally mounted MP5K-PDW, one braces the briefcase at the waist, ensures the briefcase is pointed at the enemy, and squeezes the trigger. Precision and handling are severely hampered all around, however if you need to 'hand over the goods' or look low profile while bodyguarding, this is your gun. When the briefcase is open the MP5 may be reloaded or dismounted.", - "weight": "3570 g", - "volume": "15 L", + "weight": "3800 g", + "volume": "15232 ml", + "longest_side": "544 mm", "price": 480000, "price_postapoc": 5000, "bashing": 15, @@ -616,8 +614,9 @@ "type": "GUN", "name": { "str_sp": "USP 9mm" }, "description": "A popular pistol, widely used among law enforcement. Extensively tested for durability, it has been found to stay accurate even after being subjected to extreme abuse.", - "weight": "770 g", - "volume": "500 ml", + "weight": "771 g", + "volume": "460 ml", + "longest_side": "230 mm", "price": 68000, "price_postapoc": 2500, "to_hit": -2, @@ -697,7 +696,8 @@ "name": { "str": "Glock 17" }, "description": "Designed for all shooters, the Glock 17 is marketed towards law-enforcement and military.", "weight": "630 g", - "volume": "500 ml", + "volume": "427 ml", + "longest_side": "233 mm", "price": 69000, "price_postapoc": 2500, "to_hit": -2, @@ -909,10 +909,11 @@ "copy-from": "pistol_base", "looks_like": "glock_17", "type": "GUN", - "name": { "str": "CZ-75" }, - "description": "The CZ-75 is a semi-automatic pistol developed in Czechoslovakia, and is one of the original wonder nines. Though designed for export to western countries, it was declared a state secret; lack of international patent protection meant that many clones and variants were produced and distributed around the world, with ÄŒeská zbrojovka only joining in the 90's. This pistol remains wildly popular among competition shooters.", - "weight": "1000 g", - "volume": "526 ml", + "name": { "str": "CZ 75 B" }, + "description": "The CZ 75 B is a semi-automatic pistol developed in Czechoslovakia, and is one of the original wonder nines. Though designed for export to western countries, it was declared a state secret; lack of international patent protection meant that many clones and variants were produced and distributed around the world, with ÄŒeská zbrojovka only joining in the 90's. This pistol remains wildly popular among competition shooters.", + "weight": "998 g", + "volume": "476 ml", + "longest_side": "238 mm", "price": 10000, "price_postapoc": 2500, "to_hit": -2, @@ -940,8 +941,9 @@ "type": "GUN", "name": { "str": "Walther CCP" }, "description": "The Walther CCP is a gas-delayed blowback semi-automatic pistol intended for the concealed carry consumer market. Internally, it is nearly identical to the cult classic H&K P7. Its fixed barrel design makes it potentially more accurate than many other pistols, though this may difficult to realize with its average trigger and short sight radius.", - "weight": "570 g", - "volume": "318 ml", + "weight": "567 g", + "volume": "334 ml", + "longest_side": "194 mm", "price": 12500, "price_postapoc": 2000, "to_hit": -2, From 611e43e0ddb9318b86651db36e32f730b8d4b5c9 Mon Sep 17 00:00:00 2001 From: LaVeyanFiend <51099123+LaVeyanFiend@users.noreply.github.com> Date: Tue, 30 Jun 2020 03:13:44 -0400 Subject: [PATCH 37/41] Re-audit .40 S&W & .300 WinMag (#41692) --- data/json/items/gun/300.json | 5 ++++- data/json/items/gun/40.json | 27 ++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/data/json/items/gun/300.json b/data/json/items/gun/300.json index 166900ca6ed38..ce542b7b24ab3 100644 --- a/data/json/items/gun/300.json +++ b/data/json/items/gun/300.json @@ -8,7 +8,8 @@ "//": "http://www.guns.com/2012/05/17/remington-xm2010-army-sniper-system-esr-now-in-stores/.", "description": "A bolt-action, box-magazine-fed, sniper rifle chambered in the powerful .300 Winchester Magnum round. The M2010 had completely replaced the M24 rifle series by 2017.", "weight": "5443 g", - "volume": "7143 ml", + "volume": "6182 ml", + "longest_side": "1187 mm", "price": 1701000, "price_postapoc": 3750, "to_hit": -1, @@ -40,6 +41,7 @@ "description": "The Weatherby Mark V is one of the finest bolt action rifles. Designed in 1955 by Roy Weatherby and Fred Jennie, it has a strong action designed to safely fire high-pressure cartridges. These rifles were presented to celebrities as part of a marketing campaign.", "weight": "3730 g", "volume": "3761 ml", + "longest_side": "1183 mm", "price": 259500, "price_postapoc": 5500, "to_hit": -1, @@ -64,6 +66,7 @@ "description": "The Winchester Model 70 is a bolt action sporting rifle. It has an iconic place in American sporting culture and has been held in high regard by shooters since it was introduced in 1936.", "weight": "3520 g", "volume": "3205 ml", + "longest_side": "1198 mm", "price": 46000, "price_postapoc": 3250, "to_hit": -1, diff --git a/data/json/items/gun/40.json b/data/json/items/gun/40.json index 12e93ab4aa522..1abf3c1842973 100644 --- a/data/json/items/gun/40.json +++ b/data/json/items/gun/40.json @@ -6,8 +6,9 @@ "type": "GUN", "name": { "str": "Beretta 90-two .40 S&W" }, "description": "A more modern version of Beretta's popular 92 series of handguns, the 90-two performs largely the same. The main difference is a sleeker, almost futuristic-looking design owed in large parts to the polymer underbarrel rail cover. This one is chambered in .40 S&W.", - "weight": "921 g", - "volume": "518 ml", + "weight": "905 g", + "volume": "554 ml", + "longest_side": "250 mm", "price": 65000, "to_hit": -2, "bashing": 8, @@ -38,7 +39,8 @@ "name": { "str_sp": "Glock 22" }, "description": "A .40 S&W variant of the popular Glock 17 pistol. The standard-issue firearm of the FBI and of countless other law enforcement agencies worldwide.", "weight": "645 g", - "volume": "443 ml", + "volume": "433 ml", + "longest_side": "234 mm", "price": 69000, "price_postapoc": 1750, "to_hit": -2, @@ -86,7 +88,8 @@ "name": { "str": "Beretta Px4 Storm .40 S&W" }, "description": "Lighter than Beretta's iconic 92 series of guns, the Px4 Storm was built by utilizing light-weight polymer construction with steel inserts. Its shape was also optimized for concealed carry. This one is chambered in .40 S&W.", "weight": "785 g", - "volume": "505 ml", + "volume": "520 ml", + "longest_side": "231 mm", "price": 65000, "to_hit": -2, "bashing": 8, @@ -156,7 +159,8 @@ "name": { "str_sp": "SIG Pro .40" }, "description": "Originally marketed as a lightweight and compact alternative to older SIG handguns, the Pro .40 is popular among European police forces.", "weight": "822 g", - "volume": "523 ml", + "volume": "509 ml", + "longest_side": "221 mm", "price": 75000, "price_postapoc": 1500, "to_hit": -2, @@ -251,6 +255,7 @@ "description": "A homemade 6-shot revolver. While it's not as good as the pre-Cataclysm manufactured weapons, it's a decent piece of work, all things considered.", "weight": "1333 g", "volume": "750 ml", + "longest_side": "33 cm", "price": 15000, "price_postapoc": 750, "to_hit": -2, @@ -290,6 +295,7 @@ "description": "The Smith and Wesson 610 is a classic six-shooter revolver chambered for 10mm rounds, or for S&W's own .40 round.", "weight": "1420 g", "volume": "754 ml", + "longest_side": "332 mm", "price": 74000, "price_postapoc": 2250, "to_hit": -2, @@ -322,8 +328,9 @@ "type": "GUN", "name": { "str": "Browning Hi-Power .40 S&W" }, "description": "The Browning Hi-Power is a semi-automatic handgun developed shortly before the second world war. Widely issued since then, it remains in use by India, Canada and Australia. This is a commercial variant produced by Browning Arms in .40 S&W.", - "weight": "900 g", - "volume": "418 ml", + "weight": "907 g", + "volume": "274 ml", + "longest_side": "228 mm", "price": 54000, "price_postapoc": 2000, "to_hit": -2, @@ -352,7 +359,8 @@ "name": { "str": "Walther PPQ .40 S&W" }, "description": "The Walther PPQ is a semi-automatic pistol originating from the Walther P99QA, and maintains compatibility with some of its predecessor's accessories. This model is chambered in .40 S&W.", "weight": "625 g", - "volume": "422 ml", + "volume": "440 ml", + "longest_side": "215 mm", "price": 72500, "price_postapoc": 2000, "bashing": 8, @@ -380,7 +388,8 @@ "name": { "str": "Hi-Point Model JCP" }, "description": "The Hi-Point Model JCP is a blowback operated semi-automatic pistol designed by Hi-Point Firearms, which is known for making inexpensive firearms, and for making said firearms bulky and uncomfortable. Hi-Points have slides made with a zinc pot-metal which is relatively fragile compared to steel slides.", "weight": "990 g", - "volume": "703 ml", + "volume": "546 ml", + "longest_side": "234 mm", "price": 7500, "price_postapoc": 2000, "to_hit": -2, From 38883252e0e1a929343bd0ff21d7a2b288d0e9c5 Mon Sep 17 00:00:00 2001 From: Fris0uman <41293484+Fris0uman@users.noreply.github.com> Date: Tue, 30 Jun 2020 09:14:23 +0200 Subject: [PATCH 38/41] [My Sweet Cataclysm] Gum is forever (#41032) --- data/json/field_type.json | 25 +++++++++++++- .../mods/My_Sweet_Cataclysm/sweet_effect.json | 3 +- .../My_Sweet_Cataclysm/sweet_field_type.json | 8 ++--- doc/EFFECTS_JSON.md | 5 +++ doc/JSON_INFO.md | 1 + src/character.cpp | 33 +++++++++++++++++++ src/character.h | 1 + src/creature.cpp | 15 ++++++++- src/creature.h | 1 + src/field.cpp | 5 +++ src/field.h | 1 + src/field_type.cpp | 2 ++ src/field_type.h | 2 ++ src/map.cpp | 27 ++++++++------- src/map_field.cpp | 20 +++-------- 15 files changed, 114 insertions(+), 35 deletions(-) diff --git a/data/json/field_type.json b/data/json/field_type.json index 76f8b860bb0c5..d0439ec43ce28 100644 --- a/data/json/field_type.json +++ b/data/json/field_type.json @@ -76,9 +76,32 @@ "id": "fd_web", "type": "field_type", "legacy_enum_id": 5, - "intensity_levels": [ { "name": "cobwebs", "sym": "}" }, { "name": "webs" }, { "name": "thick webs", "transparent": false } ], + "intensity_levels": [ + { + "name": "cobwebs", + "sym": "}", + "effects": [ + { "effect_id": "webbed", "intensity": 1, "min_duration": "1 m", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "webs", + "effects": [ + { "effect_id": "webbed", "intensity": 2, "min_duration": "1 m", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "thick webs", + "transparent": false, + "effects": [ + { "effect_id": "webbed", "intensity": 3, "min_duration": "1 m", "immune_in_vehicle": true, "is_environmental": false } + ] + } + ], "description_affix": "covered_in", "immunity_data": { "traits": [ "WEB_WALKER" ] }, + "immune_mtypes": [ "mon_spider_web", "mon_spider_web_s" ], + "decrease_intensity_on_contact": true, "priority": 2, "phase": "solid", "display_items": false, diff --git a/data/mods/My_Sweet_Cataclysm/sweet_effect.json b/data/mods/My_Sweet_Cataclysm/sweet_effect.json index 416caf3b97bf7..310b98db195a9 100644 --- a/data/mods/My_Sweet_Cataclysm/sweet_effect.json +++ b/data/mods/My_Sweet_Cataclysm/sweet_effect.json @@ -7,10 +7,11 @@ "apply_message": "You're covered in gum!", "rating": "bad", "miss_messages": [ [ "The gum webs constrict your movement.", 4 ] ], - "max_intensity": 3, + "max_intensity": 6, "max_duration": "30 s", "base_mods": { "speed_mod": [ -20 ] }, "scaling_mods": { "speed_mod": [ -20 ] }, + "flags": [ "EFFECT_IMPEDING" ], "show_in_info": true } ] diff --git a/data/mods/My_Sweet_Cataclysm/sweet_field_type.json b/data/mods/My_Sweet_Cataclysm/sweet_field_type.json index 77c43ffcd5850..73df21fc1a46c 100644 --- a/data/mods/My_Sweet_Cataclysm/sweet_field_type.json +++ b/data/mods/My_Sweet_Cataclysm/sweet_field_type.json @@ -4,6 +4,7 @@ "type": "field_type", "legacy_enum_id": 5, "immune_mtypes": [ "mon_spider_gum" ], + "decrease_intensity_on_contact": true, "intensity_levels": [ { "name": "flimsy gum webs", @@ -12,7 +13,7 @@ "effects": [ { "effect_id": "gummed", - "intensity": 1, + "intensity": 2, "min_duration": "2 seconds", "immune_in_vehicle": true, "is_environmental": false, @@ -27,7 +28,7 @@ "effects": [ { "effect_id": "gummed", - "intensity": 2, + "intensity": 4, "min_duration": "20 seconds", "immune_in_vehicle": true, "is_environmental": false, @@ -43,7 +44,7 @@ "effects": [ { "effect_id": "gummed", - "intensity": 3, + "intensity": 6, "min_duration": "40 seconds", "immune_in_vehicle": true, "is_environmental": false, @@ -57,7 +58,6 @@ "description_affix": "covered_in", "priority": 2, "phase": "solid", - "half_life": "2 h", "bash": { "str_min": 1, "str_max": 3, diff --git a/doc/EFFECTS_JSON.md b/doc/EFFECTS_JSON.md index 5f637266e3e5b..56db3f15fbf4d 100644 --- a/doc/EFFECTS_JSON.md +++ b/doc/EFFECTS_JSON.md @@ -286,6 +286,11 @@ main part (arms, head, legs, etc.). them more pkill. "pain_sizing" and "hurt_sizing" cause large/huge mutations to affect the chance of pain and hurt effects triggering. "harmful_cough" means that the coughs caused by this effect can hurt the player. +### Flags + +"EFFECT_INVISIBLE" Character affected by an effect with this flag are invisible. +"EFFECT_IMPEDING" Character affected by an effect with this flag can't move until they break free from the effect. Breaking free requires a strenght check: `x_in_y( get_str(), 6 * get_effect_int( eff_id )` + ### Effect effects ```C++ "base_mods" : { diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 0848d94c2c5d6..138b3ed9092ba 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -3450,6 +3450,7 @@ Setting of sprite sheets. Same as `tiles-new` field in `tile_config`. Sprite fil { "name": "shadow", // name of this level of intensity "light_override": 3.7 } //light level on the tile occupied by this field will be set at 3.7 not matter the ambient light. ], + "decrease_intensity_on_contact": true, // Decrease the field intensity by one each time a character walk on it. "bash": { "str_min": 1, // lower bracket of bashing damage required to bash "str_max": 3, // higher bracket diff --git a/src/character.cpp b/src/character.cpp index d04adcca5d0e3..af7163d62b45d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -339,6 +339,7 @@ static const std::string flag_BELTED( "BELTED" ); static const std::string flag_BLIND( "BLIND" ); static const std::string flag_DEAF( "DEAF" ); static const std::string flag_DISABLE_SIGHTS( "DISABLE_SIGHTS" ); +static const std::string flag_EFFECT_IMPEDING( "EFFECT_IMPEDING" ); static const std::string flag_EFFECT_INVISIBLE( "EFFECT_INVISIBLE" ); static const std::string flag_EFFECT_NIGHT_VISION( "EFFECT_NIGHT_VISION" ); static const std::string flag_FIX_NEARSIGHT( "FIX_NEARSIGHT" ); @@ -1558,6 +1559,29 @@ void Character::try_remove_webs() } } +void Character::try_remove_impeding_effect() +{ + for( const effect &eff : get_effects_with_flag( flag_EFFECT_IMPEDING ) ) { + const efftype_id &eff_id = eff.get_id(); + if( is_mounted() ) { + auto mon = mounted_creature.get(); + if( x_in_y( mon->type->melee_dice * mon->type->melee_sides, + 6 * get_effect_int( eff_id ) ) ) { + add_msg( _( "The %s breaks free!" ), mon->get_name() ); + mon->remove_effect( eff_id ); + remove_effect( eff_id ); + } + /** @EFFECT_STR increases chance to escape webs */ + } else if( x_in_y( get_str(), 6 * get_effect_int( eff_id ) ) ) { + add_msg_player_or_npc( m_good, _( "You free yourself!" ), + _( " frees themselves!" ) ); + remove_effect( eff_id ); + } else { + add_msg_if_player( _( "You try to free yourself, but can't!" ) ); + } + } +} + bool Character::move_effects( bool attacking ) { if( has_effect( effect_downed ) ) { @@ -1585,6 +1609,11 @@ bool Character::move_effects( bool attacking ) try_remove_crushed(); return false; } + if( has_effect_with_flag( flag_EFFECT_IMPEDING ) ) { + try_remove_impeding_effect(); + return false; + } + // Below this point are things that allow for movement if they succeed // Currently we only have one thing that forces movement if you succeed, should we get more @@ -1627,6 +1656,10 @@ void Character::wait_effects( bool attacking ) try_remove_webs(); return; } + if( has_effect_with_flag( flag_EFFECT_IMPEDING ) ) { + try_remove_impeding_effect(); + return; + } if( has_effect( effect_grabbed ) && !attacking && !try_remove_grab() ) { return; } diff --git a/src/character.h b/src/character.h index 523ef41f86594..39bef0767288f 100644 --- a/src/character.h +++ b/src/character.h @@ -639,6 +639,7 @@ class Character : public Creature, public visitable void try_remove_heavysnare(); void try_remove_crushed(); void try_remove_webs(); + void try_remove_impeding_effect(); /** Check against the character's current movement mode */ bool movement_mode_is( const move_mode_id &mode ) const; diff --git a/src/creature.cpp b/src/creature.cpp index 25c59fc1655d9..bc01e992e99ec 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1145,7 +1145,7 @@ bool Creature::has_effect_with_flag( const std::string &flag, body_part bp ) con { for( auto &elem : *effects ) { for( const std::pair &_it : elem.second ) { - if( bp == _it.first && _it.second.has_flag( flag ) ) { + if( ( bp == _it.first || bp == num_bp ) && _it.second.has_flag( flag ) ) { return true; } } @@ -1153,6 +1153,19 @@ bool Creature::has_effect_with_flag( const std::string &flag, body_part bp ) con return false; } +std::vector Creature::get_effects_with_flag( const std::string &flag ) const +{ + std::vector effs; + for( auto &elem : *effects ) { + for( const std::pair &_it : elem.second ) { + if( _it.second.has_flag( flag ) ) { + effs.push_back( _it.second ); + } + } + } + return effs; +} + effect &Creature::get_effect( const efftype_id &eff_id, body_part bp ) { return const_cast( const_cast( this )->get_effect( eff_id, bp ) ); diff --git a/src/creature.h b/src/creature.h index f17b3a727eafd..e19c3ff4a3e09 100644 --- a/src/creature.h +++ b/src/creature.h @@ -494,6 +494,7 @@ class Creature bool has_effect( const efftype_id &eff_id, body_part bp = num_bp ) const; /** Check if creature has any effect with the given flag. */ bool has_effect_with_flag( const std::string &flag, body_part bp = num_bp ) const; + std::vector get_effects_with_flag( const std::string &flag ) const; /** Return the effect that matches the given arguments exactly. */ const effect &get_effect( const efftype_id &eff_id, body_part bp = num_bp ) const; effect &get_effect( const efftype_id &eff_id, body_part bp = num_bp ); diff --git a/src/field.cpp b/src/field.cpp index bbf8102195051..062b09d867694 100644 --- a/src/field.cpp +++ b/src/field.cpp @@ -130,6 +130,11 @@ int field_entry::set_field_intensity( int new_intensity ) } +void field_entry::mod_field_intensity( int mod ) +{ + set_field_intensity( get_field_intensity() + mod ); +} + time_duration field_entry::get_field_age() const { return age; diff --git a/src/field.h b/src/field.h index 38aabd02041a4..1668c8cf3d56d 100644 --- a/src/field.h +++ b/src/field.h @@ -62,6 +62,7 @@ class field_entry int get_field_intensity() const; // Allows you to modify the intensity of the current field entry. int set_field_intensity( int new_intensity ); + void mod_field_intensity( int mod ); /// @returns @ref age. time_duration get_field_age() const; diff --git a/src/field_type.cpp b/src/field_type.cpp index d6ae14b553938..fa21bd996e471 100644 --- a/src/field_type.cpp +++ b/src/field_type.cpp @@ -250,6 +250,8 @@ void field_type::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "display_field", display_field, false ); optional( jo, was_loaded, "wandering_field", wandering_field_id, "fd_null" ); + optional( jo, was_loaded, "decrease_intensity_on_contact", decrease_intensity_on_contact, false ); + bash_info.load( jo, "bash", map_bash_info::field ); if( was_loaded && jo.has_member( "copy-from" ) && looks_like.empty() ) { looks_like = jo.get_string( "copy-from" ); diff --git a/src/field_type.h b/src/field_type.h index d306a5d155963..6110bc4db642b 100644 --- a/src/field_type.h +++ b/src/field_type.h @@ -163,6 +163,8 @@ struct field_type { field_type_id wandering_field; std::string looks_like; + bool decrease_intensity_on_contact = false; + public: const field_intensity_level &get_intensity_level( int level = 0 ) const; std::string get_name( int level = 0 ) const { diff --git a/src/map.cpp b/src/map.cpp index e9b3edbb1bad5..53e08c0711b5a 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3347,10 +3347,12 @@ void map::bash_vehicle( const tripoint &p, bash_params ¶ms ) void map::bash_field( const tripoint &p, bash_params ¶ms ) { - if( get_field( p, fd_web ) != nullptr ) { - params.did_bash = true; - params.bashed_solid = true; // To prevent bashing furniture/vehicles - remove_field( p, fd_web ); + for( const std::pair &fd : field_at( p ) ) { + if( fd.first->bash_info.str_min > -1 ) { + params.did_bash = true; + params.bashed_solid = true; // To prevent bashing furniture/vehicles + remove_field( p, fd.first ); + } } } @@ -3650,14 +3652,15 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) dam = std::max( 0.0f, dam ); // Check fields? - const field_entry *fieldhit = get_field( p, fd_web ); - if( fieldhit != nullptr ) { - if( inc ) { - add_field( p, fd_fire, fieldhit->get_field_intensity() - 1 ); - } else if( dam > 5 + fieldhit->get_field_intensity() * 5 && - one_in( 5 - fieldhit->get_field_intensity() ) ) { - dam -= rng( 1, 2 + fieldhit->get_field_intensity() * 2 ); - remove_field( p, fd_web ); + for( const std::pair &fd : field_at( p ) ) { + if( fd.first->bash_info.str_min > 0 ) { + if( inc ) { + add_field( p, fd_fire, fd.second.get_field_intensity() - 1 ); + } else if( dam > 5 + fd.second.get_field_intensity() * 5 && + one_in( 5 - fd.second.get_field_intensity() ) ) { + dam -= rng( 1, 2 + fd.second.get_field_intensity() * 2 ); + remove_field( p, fd.first ); + } } } diff --git a/src/map_field.cpp b/src/map_field.cpp index f49f38586b05b..229ed9f24c59e 100644 --- a/src/map_field.cpp +++ b/src/map_field.cpp @@ -1382,22 +1382,6 @@ void map::player_in_field( player &u ) // Do things based on what field effect we are currently in. const field_type_id ft = cur.get_field_type(); - if( ft == fd_web ) { - // If we are in a web, can't walk in webs or are in a vehicle, get webbed maybe. - // Moving through multiple webs stacks the effect. - if( !u.has_trait( trait_WEB_WALKER ) && !u.in_vehicle ) { - // Between 5 and 15 minus your current web level. - u.add_effect( effect_webbed, 1_turns, num_bp, true, cur.get_field_intensity() ); - // It is spent. - cur.set_field_intensity( 0 ); - continue; - // If you are in a vehicle destroy the web. - // It should of been destroyed when you ran over it anyway. - } else if( u.in_vehicle ) { - cur.set_field_intensity( 0 ); - continue; - } - } if( ft == fd_acid ) { // Assume vehicles block acid damage entirely, // you're certainly not standing in it. @@ -1723,6 +1707,10 @@ void map::creature_in_field( Creature &critter ) const field_type_id cur_field_id = cur_field_entry.get_field_type(); for( const auto &fe : cur_field_entry.field_effects() ) { + // the field is decreased even if you are in a vehicle + if( cur_field_id->decrease_intensity_on_contact ) { + cur_field_entry.mod_field_intensity( -1 ); + } if( in_vehicle && fe.immune_in_vehicle ) { continue; } From 24f5590b5cfce038c3154fa570d0b2711e7de385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Karlsson?= Date: Tue, 30 Jun 2020 09:18:31 +0200 Subject: [PATCH 39/41] Add longest_side to items/tool/knives.json (#41658) * Add longest_side to items/tool/knives.json Also, adjust starting equipment for beekeeper, adding a sheath for the honey scraper. --- data/json/items/tool/knives.json | 3 +++ data/json/professions.json | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/data/json/items/tool/knives.json b/data/json/items/tool/knives.json index ac389deb2daa0..7c38c98bb589d 100644 --- a/data/json/items/tool/knives.json +++ b/data/json/items/tool/knives.json @@ -6,6 +6,7 @@ "description": "A knife consisting of crudely-worked copper, and a simple handle. Primitive, but a step above stone-age.", "weight": "650 g", "volume": "250 ml", + "longest_side": "25 cm", "price": 3000, "price_postapoc": 10, "to_hit": -1, @@ -44,6 +45,7 @@ "description": "A sharp, knife-like tool used in harvesting honey from beehives. Makes a passable melee weapon.", "weight": "580 g", "volume": "250 ml", + "longest_side": "46 cm", "price": 1000, "price_postapoc": 100, "to_hit": -1, @@ -79,6 +81,7 @@ "description": "This is a sharpened stone set into a hollowed handle. Not nearly as usable as a proper knife, but it's better than nothing.", "weight": "453 g", "volume": "250 ml", + "longest_side": "25 cm", "price": 0, "price_postapoc": 0, "to_hit": -3, diff --git a/data/json/professions.json b/data/json/professions.json index 66f8cebed9c77..b895a804c7a01 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -651,7 +651,6 @@ "items": { "both": { "items": [ - "honey_scraper", "beekeeping_hood", "beekeeping_suit", "beekeeping_gloves", @@ -662,7 +661,7 @@ "honey_bottled", "honey_bottled" ], - "entries": [ { "group": "charged_cell_phone" } ] + "entries": [ { "group": "charged_cell_phone" }, { "item": "honey_scraper", "container-item": "sheath" } ] }, "male": [ "boxer_briefs" ], "female": [ "bra", "panties" ] From 6d1f70cc74311198530738509c3328b4ceb575b4 Mon Sep 17 00:00:00 2001 From: johnrdconnolly <59102789+johnrdconnolly@users.noreply.github.com> Date: Tue, 30 Jun 2020 00:19:12 -0700 Subject: [PATCH 40/41] Update firerighting.json lengths (#41645) --- data/json/items/tool/firefighting.json | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/data/json/items/tool/firefighting.json b/data/json/items/tool/firefighting.json index d7d4dd8b44ed2..36e62708d7c11 100644 --- a/data/json/items/tool/firefighting.json +++ b/data/json/items/tool/firefighting.json @@ -14,6 +14,7 @@ "techniques": [ "WBLOCK_1" ], "weight": "907 g", "volume": "1 L", + "longest_side": "40 cm", "bashing": 17, "cutting": 28, "to_hit": -2, @@ -25,8 +26,9 @@ "type": "TOOL", "name": { "str": "large fire extinguisher" }, "description": "This is an emergency fire extinguisher containing five gallons of fire retardant foam. It would be useful for putting out adjacent fires.", - "weight": "13813 g", + "weight": "7030 g", "volume": "20000 ml", + "longest_side": "50 cm", "price": 5000, "price_postapoc": 100, "to_hit": -4, @@ -57,6 +59,7 @@ "weight": "2520 g", "volume": "2 L", "price": 20000, + "longest_side": "90 cm", "price_postapoc": 1500, "bashing": 17, "cutting": 34, @@ -73,8 +76,9 @@ "type": "TOOL", "name": { "str": "Halligan bar" }, "description": "This is a heavy multiple-use tool commonly carried by firefighters, law enforcement, and military rescue units. Use it to open locked doors without destroying them or to lift manhole covers. You could also wield it to bash some heads in.", - "weight": "3600 g", + "weight": "5443 g", "volume": "1250 ml", + "longest_side": "60 cm", "price": 7500, "price_postapoc": 1500, "bashing": 40, @@ -85,15 +89,16 @@ "techniques": [ "WBLOCK_1", "BRUTAL", "SWEEP" ], "qualities": [ [ "PRY", 4 ], [ "HAMMER", 2 ], [ "DIG", 1 ] ], "use_action": [ "HAMMER", "CROWBAR" ], - "flags": [ "DURABLE_MELEE", "BELT_CLIP", "STAB" ] + "flags": [ "DURABLE_MELEE", "BELT_CLIP", "STAB", "SHEATH_AXE" ] }, { "id": "sm_extinguisher", "type": "TOOL", "name": { "str": "small fire extinguisher" }, "description": "This is a hand held fire extinguisher containing a liter of highly compressed CO2 gas. It would be useful for putting out adjacent fires.", - "weight": "2267 g", + "weight": "1133 g", "volume": "2000 ml", + "longest_side": "40 cm", "price": 4000, "price_postapoc": 50, "to_hit": -1, @@ -178,6 +183,7 @@ "flags": [ "DURABLE_MELEE", "REACH_ATTACK", "NONCONDUCTIVE", "SHEATH_SPEAR", "ALWAYS_TWOHAND" ], "weight": "3100 g", "volume": "3250 ml", + "longest_side": "160 cm", "bashing": 20, "cutting": 6, "to_hit": -1, @@ -197,6 +203,7 @@ "flags": [ "DURABLE_MELEE", "STAB", "SHEATH_AXE" ], "weight": "2900 g", "volume": "1900 ml", + "longest_side": "90 cm", "bashing": 15, "cutting": 13, "to_hit": -1, From 537b77378619d28aaf8c617b0f82317ef66c251d Mon Sep 17 00:00:00 2001 From: nexusmrsep <39925111+nexusmrsep@users.noreply.github.com> Date: Tue, 30 Jun 2020 09:21:52 +0200 Subject: [PATCH 41/41] Skill based achievements (#41657) --- data/json/achievements.json | 435 +++++++++++++++ data/json/statistics.json | 1044 +++++++++++++++++++++++++++++++++++ src/player.cpp | 3 + 3 files changed, 1482 insertions(+) diff --git a/data/json/achievements.json b/data/json/achievements.json index bbe0bf7f184c1..66decd2db0948 100644 --- a/data/json/achievements.json +++ b/data/json/achievements.json @@ -286,5 +286,440 @@ { "event_statistic": "num_broken_right_arm", "is": ">=", "target": 1, "visible": "when_requirement_completed" }, { "event_statistic": "num_broken_left_arm", "is": ">=", "target": 1, "visible": "when_requirement_completed" } ] + }, + { + "id": "achievement_lvl_7_barter", + "type": "achievement", + "name": "Free Trader", + "description": "Extraordinary gizmos for obscenely low prices!", + "requirements": [ { "event_statistic": "num_gains_barter_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_barter", + "type": "achievement", + "name": "Cut-Me-Own-Throat Dibbler", + "description": "My Innuit friend, I'm selling you this ice for such a low price, that it's cutting me own throat.", + "requirements": [ { "event_statistic": "num_gains_barter_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_barter" ] + }, + { + "id": "achievement_lvl_7_speech", + "type": "achievement", + "name": "Eloquent", + "description": "We're frends, aren't we?", + "requirements": [ { "event_statistic": "num_gains_speech_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_speech", + "type": "achievement", + "name": "Silver Tongue", + "description": "Legend has it that you convinced a zombie hulk to go away.", + "requirements": [ { "event_statistic": "num_gains_speech_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_speech" ] + }, + { + "id": "achievement_lvl_7_computer", + "type": "achievement", + "name": "HackerMan", + "description": "This OS has a back door. There is always a back door.", + "requirements": [ { "event_statistic": "num_gains_computer_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_computer", + "type": "achievement", + "name": "Still not quite like Kevin", + "description": "It's not cheating. It's debugging.", + "requirements": [ { "event_statistic": "num_gains_computer_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_computer" ] + }, + { + "id": "achievement_lvl_7_firstaid", + "type": "achievement", + "name": "MD", + "description": "Is there a doctor in the house?", + "requirements": [ { "event_statistic": "num_gains_firstaid_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_firstaid", + "type": "achievement", + "name": "Dr House", + "description": "It's lupus.", + "requirements": [ { "event_statistic": "num_gains_firstaid_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_firstaid" ] + }, + { + "id": "achievement_lvl_7_mechanics", + "type": "achievement", + "name": "Engineer", + "description": "Just give me my wrench.", + "requirements": [ { "event_statistic": "num_gains_mechanics_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_mechanics", + "type": "achievement", + "name": "MacGyver", + "description": "This whole deal is holding on faith, spit and duct tape.", + "requirements": [ { "event_statistic": "num_gains_mechanics_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_mechanics" ] + }, + { + "id": "achievement_lvl_7_traps", + "type": "achievement", + "name": "Trapper", + "description": "A good trap doesn't discriminate between beavers and zombeavers.", + "requirements": [ { "event_statistic": "num_gains_traps_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_traps", + "type": "achievement", + "name": "Minesweeper", + "description": "All it takes is one mistake.", + "requirements": [ { "event_statistic": "num_gains_traps_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_traps" ] + }, + { + "id": "achievement_lvl_7_driving", + "type": "achievement", + "name": "Ace Driver", + "description": "No turn is too sharp.", + "requirements": [ { "event_statistic": "num_gains_driving_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_driving", + "type": "achievement", + "name": "The Stig", + "description": "Formula One is for Sunday drivers.", + "requirements": [ { "event_statistic": "num_gains_driving_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_driving" ] + }, + { + "id": "achievement_lvl_7_swimming", + "type": "achievement", + "name": "Swimmer", + "description": "Like a fish to water.", + "requirements": [ { "event_statistic": "num_gains_swimming_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_swimming", + "type": "achievement", + "name": "Michael Phelps", + "description": "Faster then Jaws.", + "requirements": [ { "event_statistic": "num_gains_swimming_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_swimming" ] + }, + { + "id": "achievement_lvl_7_fabrication", + "type": "achievement", + "name": "Do-It-Yourselfer", + "description": "Take this thing, put it in that thing, and voila.", + "requirements": [ { "event_statistic": "num_gains_fabrication_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_fabrication", + "type": "achievement", + "name": "Jack of All Trades", + "description": "With a right ammount of glue, there is nothing I can't do.", + "requirements": [ { "event_statistic": "num_gains_fabrication_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_fabrication" ] + }, + { + "id": "achievement_lvl_7_cooking", + "type": "achievement", + "name": "Master Chef", + "description": "Glazed tenderloin is a cakewalk.", + "requirements": [ { "event_statistic": "num_gains_cooking_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_cooking", + "type": "achievement", + "name": "Hell's Kitchen", + "description": "Today's menu: Soupe a l'oignon, Boeuf Bourguignon and Creme brulee.", + "requirements": [ { "event_statistic": "num_gains_cooking_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_cooking" ] + }, + { + "id": "achievement_lvl_7_tailor", + "type": "achievement", + "name": "Tailor", + "description": "A needle, a thread and a dream.", + "requirements": [ { "event_statistic": "num_gains_tailor_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_tailor", + "type": "achievement", + "name": "Fashion Designer", + "description": "Male, feamale and mutant fashion alike.", + "requirements": [ { "event_statistic": "num_gains_tailor_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_tailor" ] + }, + { + "id": "achievement_lvl_7_survival", + "type": "achievement", + "name": "Survivalist", + "description": "Survival is my game.", + "requirements": [ { "event_statistic": "num_gains_survival_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_survival", + "type": "achievement", + "name": "Bear Grylls", + "description": "So you say you can survive on your own urine?", + "requirements": [ { "event_statistic": "num_gains_survival_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_survival" ] + }, + { + "id": "achievement_lvl_7_electronics", + "type": "achievement", + "name": "Ohm's Law", + "description": "Thunder Ohm. Two volts enter, one volt leaves. Resistance is futile.", + "requirements": [ { "event_statistic": "num_gains_electronics_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_electronics", + "type": "achievement", + "name": "Nicola Tesla", + "description": "One does not simply taste a 9V battery.", + "requirements": [ { "event_statistic": "num_gains_electronics_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_electronics" ] + }, + { + "id": "achievement_lvl_7_archery", + "type": "achievement", + "name": "Bull's Eye", + "description": "Better then Legolas.", + "requirements": [ { "event_statistic": "num_gains_archery_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_archery", + "type": "achievement", + "name": "Robin Hood", + "description": "Wilhelm Tell? Never heard of.", + "requirements": [ { "event_statistic": "num_gains_archery_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_archery" ] + }, + { + "id": "achievement_lvl_7_gun", + "type": "achievement", + "name": "Eagle Eye", + "description": "Only me and my target.", + "requirements": [ { "event_statistic": "num_gains_gun_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_gun", + "type": "achievement", + "name": "Deadshot", + "description": "Don't run. You'll die tired.", + "requirements": [ { "event_statistic": "num_gains_gun_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_gun" ] + }, + { + "id": "achievement_lvl_7_launcher", + "type": "achievement", + "name": "Gunner", + "description": "Caliber makes the difference.", + "requirements": [ { "event_statistic": "num_gains_launcher_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_launcher", + "type": "achievement", + "name": "Rocket Man", + "description": "I'm sending you to the moon. In pieces.", + "requirements": [ { "event_statistic": "num_gains_launcher_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_launcher" ] + }, + { + "id": "achievement_lvl_7_pistol", + "type": "achievement", + "name": "Small But Deadly", + "description": "Caliber doesn't count when you're on the recieving side of the barrel.", + "requirements": [ { "event_statistic": "num_gains_pistol_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_pistol", + "type": "achievement", + "name": "Dirty Harry", + "description": "But being this is a .44 Magnum, the most powerful handgun in the world and would blow your head clean off, you've gotta ask yourself one question: Do I feel lucky? Well, do ya, punk?", + "requirements": [ { "event_statistic": "num_gains_pistol_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_pistol" ] + }, + { + "id": "achievement_lvl_7_rifle", + "type": "achievement", + "name": "Rifleman", + "description": "This is my rifle. There are many like it, but this one is mine. My rifle is my best friend. It is my life. I must master it as I must master my life.", + "requirements": [ { "event_statistic": "num_gains_rifle_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_rifle", + "type": "achievement", + "name": "Soldier", + "description": "Without me, my rifle is useless. Without my rifle, I am useless. I will keep my rifle clean and ready, even as I am clean and ready. We will become part of each other.", + "requirements": [ { "event_statistic": "num_gains_rifle_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_rifle" ] + }, + { + "id": "achievement_lvl_7_shotgun", + "type": "achievement", + "name": "Double Barrel, Double Fun", + "description": "When you want to hit your target nine times with one shot.", + "requirements": [ { "event_statistic": "num_gains_shotgun_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_shotgun", + "type": "achievement", + "name": "Elmer Fudd", + "description": "What's up doc? Hunting wabbits?", + "requirements": [ { "event_statistic": "num_gains_shotgun_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_shotgun" ] + }, + { + "id": "achievement_lvl_7_smg", + "type": "achievement", + "name": "Spray'n'Pray", + "description": "One will hit. It's a matter of statistics.", + "requirements": [ { "event_statistic": "num_gains_smg_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_smg", + "type": "achievement", + "name": "SMG Goes BRRRT!", + "description": "We definitely need more ammo.", + "requirements": [ { "event_statistic": "num_gains_smg_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_smg" ] + }, + { + "id": "achievement_lvl_7_throw", + "type": "achievement", + "name": "Yeet!", + "description": "And never come back.", + "requirements": [ { "event_statistic": "num_gains_throw_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_throw", + "type": "achievement", + "name": "Kobe Bryant", + "description": "Frag out!", + "requirements": [ { "event_statistic": "num_gains_throw_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_throw" ] + }, + { + "id": "achievement_lvl_7_melee", + "type": "achievement", + "name": "Brawler", + "description": "Bottle in left hand, chair leg in right hand.", + "requirements": [ { "event_statistic": "num_gains_melee_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_melee", + "type": "achievement", + "name": "Street Fighter", + "description": "It's winning that matters, not the style.", + "requirements": [ { "event_statistic": "num_gains_melee_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_melee" ] + }, + { + "id": "achievement_lvl_7_bashing", + "type": "achievement", + "name": "Batter", + "description": "Every strike brings me closer to a home run.", + "requirements": [ { "event_statistic": "num_gains_bashing_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_bashing", + "type": "achievement", + "name": "Stone Age", + "description": "Cudgel was humanity's first tool. And it may be it's last, so why not master it?", + "requirements": [ { "event_statistic": "num_gains_bashing_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_bashing" ] + }, + { + "id": "achievement_lvl_7_cutting", + "type": "achievement", + "name": "Way of the Sword", + "description": "When the sword is once drawn, the passions of men observe no bounds of moderation.", + "requirements": [ { "event_statistic": "num_gains_cutting_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_cutting", + "type": "achievement", + "name": "Miyamoto Musashi", + "description": "The sword has to be more than a simple weapon; it has to be an answer to life's questions.", + "requirements": [ { "event_statistic": "num_gains_cutting_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_cutting" ] + }, + { + "id": "achievement_lvl_7_dodge", + "type": "achievement", + "name": "Elusive", + "description": "A strongest of blows is nothing if it doesn't land.", + "requirements": [ { "event_statistic": "num_gains_dodge_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_dodge", + "type": "achievement", + "name": "Neo", + "description": "But can you dodge a bullet?", + "requirements": [ { "event_statistic": "num_gains_dodge_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_dodge" ] + }, + { + "id": "achievement_lvl_7_stabbing", + "type": "achievement", + "name": "Cold Steel", + "description": "While you were partying, I studied the blade.", + "requirements": [ { "event_statistic": "num_gains_stabbing_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_stabbing", + "type": "achievement", + "name": "Jack the Ripper", + "description": "Is this a dagger which I see before me, the handle toward my hand? Come, let me clutch thee.", + "requirements": [ { "event_statistic": "num_gains_stabbing_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_stabbing" ] + }, + { + "id": "achievement_lvl_7_unarmed", + "type": "achievement", + "name": "Road to Shaolin", + "description": "I feel an army in my fist.", + "requirements": [ { "event_statistic": "num_gains_unarmed_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_unarmed", + "type": "achievement", + "name": "Mr Miyagi", + "description": "To be your own weapon.", + "requirements": [ { "event_statistic": "num_gains_unarmed_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_unarmed" ] + }, + { + "id": "achievement_lvl_7_lockpick", + "type": "achievement", + "name": "Burglar", + "description": "Crowbar? Such a barbarity.", + "requirements": [ { "event_statistic": "num_gains_lockpick_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_lockpick", + "type": "achievement", + "name": "Locksmith", + "description": "If there is a lock, there is a key.", + "requirements": [ { "event_statistic": "num_gains_lockpick_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_lockpick" ] + }, + { + "id": "achievement_lvl_7_chemistry", + "type": "achievement", + "name": "Periodic Table", + "description": "It's somewhat like cooking. Just don't lick the spoon.", + "requirements": [ { "event_statistic": "num_gains_chemistry_level_7", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_lvl_10_chemistry", + "type": "achievement", + "name": "Heisenberg", + "description": "You all know who I am. I'm the cook. Say my name.", + "requirements": [ { "event_statistic": "num_gains_chemistry_level_10", "is": ">=", "target": 1 } ], + "hidden_by": [ "achievement_lvl_7_chemistry" ] } ] diff --git a/data/json/statistics.json b/data/json/statistics.json index 3ef7f023f5441..417e625ebce40 100644 --- a/data/json/statistics.json +++ b/data/json/statistics.json @@ -523,6 +523,1050 @@ "event_transformation": "avatar_gains_skill_level", "description": { "str": "skill level gained", "str_pl": "skill levels gained" } }, + { + "id": "avatar_gains_barter_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "barter" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_barter_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_barter_level_7", + "description": { "str_sp": "bartering skill level 7 gained" } + }, + { + "id": "avatar_gains_speech_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "speech" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_speech_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_speech_level_7", + "description": { "str_sp": "speaking skill level 7 gained" } + }, + { + "id": "avatar_gains_computer_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "computer" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_computer_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_computer_level_7", + "description": { "str_sp": "computers skill level 7 gained" } + }, + { + "id": "avatar_gains_firstaid_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "firstaid" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_firstaid_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_firstaid_level_7", + "description": { "str_sp": "first aid skill level 7 gained" } + }, + { + "id": "avatar_gains_mechanics_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "mechanics" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_mechanics_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_mechanics_level_7", + "description": { "str_sp": "mechanics skill level 7 gained" } + }, + { + "id": "avatar_gains_traps_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "traps" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_traps_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_traps_level_7", + "description": { "str_sp": "trapping skill level 7 gained" } + }, + { + "id": "avatar_gains_driving_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "driving" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_driving_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_driving_level_7", + "description": { "str_sp": "driving skill level 7 gained" } + }, + { + "id": "avatar_gains_swimming_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "swimming" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_swimming_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_swimming_level_7", + "description": { "str_sp": "swimming skill level 7 gained" } + }, + { + "id": "avatar_gains_fabrication_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "fabrication" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_fabrication_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_fabrication_level_7", + "description": { "str_sp": "fabrication skill level 7 gained" } + }, + { + "id": "avatar_gains_cooking_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "cooking" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_cooking_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_cooking_level_7", + "description": { "str_sp": "cooking skill level 7 gained" } + }, + { + "id": "avatar_gains_tailor_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "tailor" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_tailor_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_tailor_level_7", + "description": { "str_sp": "tailoring skill level 7 gained" } + }, + { + "id": "avatar_gains_survival_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "survival" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_survival_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_survival_level_7", + "description": { "str_sp": "survival skill level 7 gained" } + }, + { + "id": "avatar_gains_electronics_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "electronics" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_electronics_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_electronics_level_7", + "description": { "str_sp": "electronics skill level 7 gained" } + }, + { + "id": "avatar_gains_archery_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "archery" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_archery_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_archery_level_7", + "description": { "str_sp": "archery skill level 7 gained" } + }, + { + "id": "avatar_gains_gun_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "gun" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_gun_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_gun_level_7", + "description": { "str_sp": "marksmanship skill level 7 gained" } + }, + { + "id": "avatar_gains_launcher_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "launcher" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_launcher_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_launcher_level_7", + "description": { "str_sp": "launchers skill level 7 gained" } + }, + { + "id": "avatar_gains_pistol_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "pistol" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_pistol_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_pistol_level_7", + "description": { "str_sp": "handguns skill level 7 gained" } + }, + { + "id": "avatar_gains_rifle_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "rifle" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_rifle_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_survival_level_7", + "description": { "str_sp": "rifles skill level 7 gained" } + }, + { + "id": "avatar_gains_shotgun_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "shotgun" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_shotgun_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_shotgun_level_7", + "description": { "str_sp": "shotguns skill level 7 gained" } + }, + { + "id": "avatar_gains_smg_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "smg" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_smg_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_smg_level_7", + "description": { "str_sp": "submachine guns skill level 7 gained" } + }, + { + "id": "avatar_gains_throw_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "throw" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_throw_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_throw_level_7", + "description": { "str_sp": "throwing skill level 7 gained" } + }, + { + "id": "avatar_gains_melee_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "melee" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_melee_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_melee_level_7", + "description": { "str_sp": "melee skill level 7 gained" } + }, + { + "id": "avatar_gains_bashing_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "bashing" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_bashing_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_bashing_level_7", + "description": { "str_sp": "bashing weapons skill level 7 gained" } + }, + { + "id": "avatar_gains_cutting_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "cutting" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_cutting_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_cutting_level_7", + "description": { "str_sp": "cutting weapons skill level 7 gained" } + }, + { + "id": "avatar_gains_dodge_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "dodge" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_dodge_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_dodge_level_7", + "description": { "str_sp": "dodging skill level 7 gained" } + }, + { + "id": "avatar_gains_stabbing_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "stabbing" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_stabbing_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_stabbing_level_7", + "description": { "str_sp": "piercing weapons skill level 7 gained" } + }, + { + "id": "avatar_gains_unarmed_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "unarmed" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_unarmed_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_unarmed_level_7", + "description": { "str_sp": "unarmed skill level 7 gained" } + }, + { + "id": "avatar_gains_lockpick_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "lockpick" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_lockpick_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_lockpick_level_7", + "description": { "str_sp": "lock picking skill level 7 gained" } + }, + { + "id": "avatar_gains_chemistry_level_7", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "chemistry" ] }, + "new_level": { "equals": [ "int", "7" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_chemistry_level_7", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_chemistry_level_7", + "description": { "str_sp": "chemistry skill level 7 gained" } + }, + { + "id": "avatar_gains_barter_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "barter" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_barter_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_barter_level_10", + "description": { "str_sp": "bartering skill level 10 gained" } + }, + { + "id": "avatar_gains_speech_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "speech" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_speech_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_speech_level_10", + "description": { "str_sp": "speaking skill level 10 gained" } + }, + { + "id": "avatar_gains_computer_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "computer" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_computer_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_computer_level_10", + "description": { "str_sp": "computers skill level 10 gained" } + }, + { + "id": "avatar_gains_firstaid_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "firstaid" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_firstaid_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_firstaid_level_10", + "description": { "str_sp": "first aid skill level 10 gained" } + }, + { + "id": "avatar_gains_mechanics_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "mechanics" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_mechanics_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_mechanics_level_10", + "description": { "str_sp": "mechanics skill level 10 gained" } + }, + { + "id": "avatar_gains_traps_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "traps" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_traps_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_traps_level_10", + "description": { "str_sp": "trapping skill level 10 gained" } + }, + { + "id": "avatar_gains_driving_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "driving" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_driving_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_driving_level_10", + "description": { "str_sp": "driving skill level 10 gained" } + }, + { + "id": "avatar_gains_swimming_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "swimming" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_swimming_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_swimming_level_10", + "description": { "str_sp": "swimming skill level 10 gained" } + }, + { + "id": "avatar_gains_fabrication_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "fabrication" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_fabrication_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_fabrication_level_10", + "description": { "str_sp": "fabrication skill level 10 gained" } + }, + { + "id": "avatar_gains_cooking_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "cooking" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_cooking_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_cooking_level_10", + "description": { "str_sp": "cooking skill level 10 gained" } + }, + { + "id": "avatar_gains_tailor_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "tailor" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_tailor_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_tailor_level_10", + "description": { "str_sp": "tailoring skill level 10 gained" } + }, + { + "id": "avatar_gains_survival_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "survival" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_survival_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_survival_level_10", + "description": { "str_sp": "survival skill level 10 gained" } + }, + { + "id": "avatar_gains_electronics_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "electronics" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_electronics_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_electronics_level_10", + "description": { "str_sp": "electronics skill level 10 gained" } + }, + { + "id": "avatar_gains_archery_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "archery" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_archery_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_archery_level_10", + "description": { "str_sp": "archery skill level 10 gained" } + }, + { + "id": "avatar_gains_gun_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "gun" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_gun_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_gun_level_10", + "description": { "str_sp": "marksmanship skill level 10 gained" } + }, + { + "id": "avatar_gains_launcher_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "launcher" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_launcher_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_launcher_level_10", + "description": { "str_sp": "launchers skill level 10 gained" } + }, + { + "id": "avatar_gains_pistol_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "pistol" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_pistol_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_pistol_level_10", + "description": { "str_sp": "handguns skill level 10 gained" } + }, + { + "id": "avatar_gains_rifle_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "rifle" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_rifle_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_survival_level_10", + "description": { "str_sp": "rifles skill level 10 gained" } + }, + { + "id": "avatar_gains_shotgun_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "shotgun" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_shotgun_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_shotgun_level_10", + "description": { "str_sp": "shotguns skill level 10 gained" } + }, + { + "id": "avatar_gains_smg_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "smg" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_smg_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_smg_level_10", + "description": { "str_sp": "submachine guns skill level 10 gained" } + }, + { + "id": "avatar_gains_throw_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "throw" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_throw_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_throw_level_10", + "description": { "str_sp": "throwing skill level 10 gained" } + }, + { + "id": "avatar_gains_melee_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "melee" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_melee_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_melee_level_10", + "description": { "str_sp": "melee skill level 10 gained" } + }, + { + "id": "avatar_gains_bashing_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "bashing" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_bashing_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_bashing_level_10", + "description": { "str_sp": "bashing weapons skill level 10 gained" } + }, + { + "id": "avatar_gains_cutting_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "cutting" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_cutting_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_cutting_level_10", + "description": { "str_sp": "cutting weapons skill level 10 gained" } + }, + { + "id": "avatar_gains_dodge_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "dodge" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_dodge_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_dodge_level_10", + "description": { "str_sp": "dodging skill level 10 gained" } + }, + { + "id": "avatar_gains_stabbing_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "stabbing" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_stabbing_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_stabbing_level_10", + "description": { "str_sp": "piercing weapons skill level 10 gained" } + }, + { + "id": "avatar_gains_unarmed_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "unarmed" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_unarmed_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_unarmed_level_10", + "description": { "str_sp": "unarmed skill level 10 gained" } + }, + { + "id": "avatar_gains_lockpick_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "lockpick" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_lockpick_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_lockpick_level_10", + "description": { "str_sp": "lock picking skill level 10 gained" } + }, + { + "id": "avatar_gains_chemistry_level_10", + "type": "event_transformation", + "event_type": "gains_skill_level", + "value_constraints": { + "character": { "equals_statistic": "avatar_id" }, + "skill": { "equals": [ "skill_id", "chemistry" ] }, + "new_level": { "equals": [ "int", "10" ] } + }, + "drop_fields": [ "character", "skill", "new_level" ] + }, + { + "id": "num_gains_chemistry_level_10", + "type": "event_statistic", + "stat_type": "count", + "event_transformation": "avatar_gains_chemistry_level_10", + "description": { "str_sp": "chemistry skill level 10 gained" } + }, { "id": "avatar_reads_book", "type": "event_transformation", diff --git a/src/player.cpp b/src/player.cpp index 1a5a371a95960..747ccab813796 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -3726,6 +3726,9 @@ void player::practice( const skill_id &id, int amount, int cap, bool suppress_wa get_skill_level_object( id ).train( amount ); int newLevel = get_skill_level( id ); std::string skill_name = skill.name(); + if( newLevel > oldLevel ) { + g->events().send( getID(), id, newLevel ); + } if( is_player() && newLevel > oldLevel ) { add_msg( m_good, _( "Your skill in %s has increased to %d!" ), skill_name, newLevel ); }