diff --git a/CMakeLists.txt b/CMakeLists.txt index a56cfa0af9c53..053e06fd02cf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option(LOCALIZE "Support for language localizations. Also enable UTF support option(LANGUAGES "Compile localization files for specified languages." "") option(DYNAMIC_LINKING "Use dynamic linking. Or use static to remove MinGW dependency instead." "ON") option(JSON_FORMAT "Build JSON formatter" "OFF") +option(CATA_CCACHE "Try to find and build with ccache" "ON") option(CATA_CLANG_TIDY_PLUGIN "Build Cata's custom clang-tidy plugin" "OFF") set(CATA_CLANG_TIDY_INCLUDE_DIR "" CACHE STRING "Path to internal clang-tidy headers required for plugin (e.g. ClangTidy.h)") set(CATA_CHECK_CLANG_TIDY "" CACHE STRING "Path to check_clang_tidy.py for plugin tests") @@ -392,9 +393,9 @@ ADD_CUSTOM_TARGET(uninstall ) find_program(CCACHE_FOUND ccache) -if(CCACHE_FOUND) +if(CCACHE_FOUND AND CATA_CCACHE) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) -endif(CCACHE_FOUND) +endif() # vim:noet diff --git a/data/core/basic.json b/data/core/basic.json index cb45312e4dc72..ac0f5f0403a8f 100644 --- a/data/core/basic.json +++ b/data/core/basic.json @@ -10,8 +10,7 @@ "type": "COMESTIBLE", "comestible_type": "DRINK", "category": "food", - "name": "water", - "name_plural": "water", + "name": { "str_sp": "water" }, "description": "Water, the stuff of life, the best thirst-quencher available. It would be safer to drink once purified.", "weight": 250, "volume": 1, diff --git a/data/json/achievements.json b/data/json/achievements.json new file mode 100644 index 0000000000000..52e6cd3563d7f --- /dev/null +++ b/data/json/achievements.json @@ -0,0 +1,15 @@ +[ + { + "id": "achievement_kill_zombie", + "type": "achievement", + "description": "One down, billions to go\u2026", + "requirements": [ { "event_statistic": "num_avatar_zombie_kills", "is": ">=", "target": 1 } ] + }, + { + "id": "achievement_kill_in_first_minute", + "type": "achievement", + "description": "Rude awakening", + "time_constraint": { "since": "game_start", "is": "<=", "target": "1 minute" }, + "requirements": [ { "event_statistic": "num_avatar_kills", "is": ">=", "target": 1 } ] + } +] diff --git a/data/json/itemgroups/Food/food.json b/data/json/itemgroups/Food/food.json index a328f8ee360d1..a167d2ba77adf 100644 --- a/data/json/itemgroups/Food/food.json +++ b/data/json/itemgroups/Food/food.json @@ -498,6 +498,7 @@ { "item": "yoghurt", "prob": 40 }, { "item": "pudding", "prob": 50 }, { "item": "V8", "prob": 15 }, + { "item": "foodplace_food", "prob": 8 }, { "item": "sandwich_t", "prob": 30 }, { "item": "sandwich_pb", "prob": 30 }, { "item": "sandwich_pbj", "prob": 30 }, @@ -760,6 +761,7 @@ { "item": "cheeseburger", "prob": 35 }, { "item": "hotdogs_frozen", "prob": 12 }, { "item": "hotdogs_cooked", "prob": 35 }, + { "item": "foodplace_food", "prob": 8 }, { "item": "chili", "prob": 20 }, { "item": "chilidogs", "prob": 20 }, { "item": "fries", "prob": 80 }, diff --git a/data/json/itemgroups/Locations_MapExtras/Arsonist_stock.json b/data/json/itemgroups/Locations_MapExtras/Arsonist_stock.json new file mode 100644 index 0000000000000..52f26816ad58d --- /dev/null +++ b/data/json/itemgroups/Locations_MapExtras/Arsonist_stock.json @@ -0,0 +1,17 @@ +[ + { + "type": "item_group", + "id": "NC_ARSONIST_STOCK", + "subtype": "collection", + "items": [ + { "item": "molotov", "count": 50 }, + { "item": "pipebomb", "count": 50 }, + { "item": "fuse", "count": 20 }, + { "item": "FMCNote", "count": 3 }, + { "item": "nail", "count": 5 }, + { "item": "rebar_rail", "count": 5 }, + { "item": "textbook_anarch", "count": 1 }, + { "item": "fertilizer_commercial", "count": 1 } + ] + } +] diff --git a/data/json/itemgroups/Locations_MapExtras/locations.json b/data/json/itemgroups/Locations_MapExtras/locations.json index 26cef7fa505e0..4695726be5701 100644 --- a/data/json/itemgroups/Locations_MapExtras/locations.json +++ b/data/json/itemgroups/Locations_MapExtras/locations.json @@ -2152,6 +2152,7 @@ [ "cotton_ball", 50 ], [ "1st_aid", 35 ], [ "survival_kit", 35 ], + [ "premium_survival_kit", 8 ], [ "saline", 10 ], [ "vitamins", 75 ], [ "gummy_vitamins", 25 ], diff --git a/data/json/itemgroups/Locations_MapExtras/locations_commercial.json b/data/json/itemgroups/Locations_MapExtras/locations_commercial.json index f8f2af2966310..f515e02965eb0 100644 --- a/data/json/itemgroups/Locations_MapExtras/locations_commercial.json +++ b/data/json/itemgroups/Locations_MapExtras/locations_commercial.json @@ -666,6 +666,7 @@ [ "flashlight", 40 ], [ "heavy_flashlight", 30 ], [ "survival_kit", 35 ], + [ "premium_survival_kit", 8 ], [ "mess_kit", 9 ], [ "popcan_stove", 2 ], [ "denat_alcohol", 2 ], diff --git a/data/json/itemgroups/activities_hobbies.json b/data/json/itemgroups/activities_hobbies.json index 6a91bddfaa310..319680afcdc5c 100644 --- a/data/json/itemgroups/activities_hobbies.json +++ b/data/json/itemgroups/activities_hobbies.json @@ -331,7 +331,8 @@ [ "esbit_stove", 10 ], [ "bottle_folding", 10 ], [ "mess_tin", 10 ], - [ "survival_kit", 30 ] + [ "survival_kit", 30 ], + [ "premium_survival_kit", 3 ] ] } ] diff --git a/data/json/itemgroups/food_service.json b/data/json/itemgroups/food_service.json index 53945d2d7ce61..1e9ea8e49fdb1 100644 --- a/data/json/itemgroups/food_service.json +++ b/data/json/itemgroups/food_service.json @@ -760,6 +760,7 @@ [ "currywurst", 5 ], [ "macaroni_cooked", 5 ], [ "lasagne", 5 ], + [ "foodplace_food", 2 ], [ "spaghetti_pesto", 5 ], [ "glazed_tenderloin", 5 ] ] @@ -781,6 +782,7 @@ [ "tomato", 20 ], [ "lettuce", 15 ], [ "zucchini", 15 ], + [ "foodplace_food", 20 ], [ "onion", 15 ], [ "chili_pepper", 15 ], [ "carrot", 15 ], @@ -842,6 +844,7 @@ [ "spaghetti_raw", 20 ], [ "lasagne_raw", 20 ], [ "macaroni_raw", 20 ], + [ "foodplace_food", 5 ], [ "knife_butcher", 10 ] ] }, diff --git a/data/json/itemgroups/misc.json b/data/json/itemgroups/misc.json index 5f0d7676bc50d..5254385ac1db4 100644 --- a/data/json/itemgroups/misc.json +++ b/data/json/itemgroups/misc.json @@ -143,6 +143,24 @@ { "item": "water_clean", "count": 2, "charges": 2, "container-item": "bottle_plastic" } ] }, + { + "id": "premium_contents", + "type": "item_group", + "subtype": "collection", + "//": "Items generated from a premium survival kit", + "items": [ + { "item": "knife_folding" }, + { "item": "flint_steel" }, + { "item": "whistle_multitool" }, + { "item": "bottle_folding" }, + { "item": "light_plus_battery_cell", "charges": 150, "container-item": "flashlight" }, + { "item": "picklocks" }, + { "item": "lifestraw" }, + { "item": "pocket_survival" }, + { "item": "solarpack" }, + { "item": "handflare", "count": 4 } + ] + }, { "id": "horse_gear", "type": "item_group", diff --git a/data/json/items/ammo.json b/data/json/items/ammo.json index 37cc7a7f594c9..12d408e73aa9f 100644 --- a/data/json/items/ammo.json +++ b/data/json/items/ammo.json @@ -240,7 +240,7 @@ "category": "spare_parts", "price": 250, "price_postapoc": 0, - "name": { "str": "plutonium slurry" }, + "name": { "str_sp": "plutonium slurry" }, "symbol": "=", "color": "green", "description": "Highly radioactive slurry. It is probably best to get far away from this.", diff --git a/data/json/items/ammo/20x66mm.json b/data/json/items/ammo/20x66mm.json index 744052c252310..ea2966d3b5254 100644 --- a/data/json/items/ammo/20x66mm.json +++ b/data/json/items/ammo/20x66mm.json @@ -102,7 +102,7 @@ "id": "20x66_inc", "copy-from": "20x66_shot", "type": "AMMO", - "name": { "str": "20x66mm incendiary" }, + "name": { "str": "20x66mm incendiary", "str_pl": "20x66mm incendiaries" }, "description": "20x66mm caseless shotgun rounds, incendiary type. Proprietary ammunition for Rivtech shotguns. Being caseless rounds, these cannot be disassembled or reloaded.", "price": 10500, "price_postapoc": 5000, diff --git a/data/json/items/ammo/50.json b/data/json/items/ammo/50.json index 45da21f0d04bc..5a9f944d361fb 100644 --- a/data/json/items/ammo/50.json +++ b/data/json/items/ammo/50.json @@ -36,7 +36,7 @@ "id": "50match", "copy-from": "50bmg", "type": "AMMO", - "name": { "str": ".50 BMG Match" }, + "name": { "str": ".50 BMG Match", "str_pl": ".50 BMG Matches" }, "description": ".50 BMG FMJ lead core ammunition manufactured with tighter tolerances for long-range competition shooting or other precision rifle use.", "count": 10, "relative": { "damage": { "damage_type": "stab", "amount": 2, "armor_penetration": -4 } }, diff --git a/data/json/items/ammo/8x40mm.json b/data/json/items/ammo/8x40mm.json index 963d3b8703230..27e885d1e9a83 100644 --- a/data/json/items/ammo/8x40mm.json +++ b/data/json/items/ammo/8x40mm.json @@ -12,7 +12,7 @@ { "id": "8mm_caseless", "type": "AMMO", - "name": { "str": "8x40mm caseless" }, + "name": { "str_sp": "8x40mm caseless" }, "//": "Cased ammo tends to be roughly $1/shot, more or less. Rivtech ammo, being New and Proprietary and Expensive, $2-2.50 or so.", "description": "8x40mm caseless rounds. Proprietary ammunition for Rivtech firearms. Being caseless rounds, these cannot be disassembled or reloaded.", "weight": "12 g", diff --git a/data/json/items/armor/jewelry.json b/data/json/items/armor/jewelry.json index 844cfe0d507d6..06b1cc2123313 100644 --- a/data/json/items/armor/jewelry.json +++ b/data/json/items/armor/jewelry.json @@ -370,7 +370,7 @@ { "id": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "garnet and gold cufflinks" }, + "name": { "str_sp": "garnet and gold cufflinks" }, "description": "A pair of cufflinks with inset garnets.", "weight": "15 g", "volume": 0, @@ -386,7 +386,7 @@ "id": "diamond_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "diamond and gold cufflinks" }, + "name": { "str_sp": "diamond and gold cufflinks" }, "description": "A pair of cufflinks with inset diamonds.", "material": [ "gold", "diamond" ], "color": "white" @@ -395,7 +395,7 @@ "id": "amethyst_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "amethyst and gold cufflinks" }, + "name": { "str_sp": "amethyst and gold cufflinks" }, "description": "A pair of cufflinks with inset amethysts.", "color": "blue" }, @@ -403,7 +403,7 @@ "id": "aquamarine_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "aquamarine and gold cufflinks" }, + "name": { "str_sp": "aquamarine and gold cufflinks" }, "description": "A pair of cufflinks with inset aquamarines.", "color": "light_blue" }, @@ -411,7 +411,7 @@ "id": "emerald_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "emerald and gold cufflinks" }, + "name": { "str_sp": "emerald and gold cufflinks" }, "description": "A pair of cufflinks with inset emeralds.", "color": "green" }, @@ -419,7 +419,7 @@ "id": "alexandrite_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "alexandrite and gold cufflinks" }, + "name": { "str_sp": "alexandrite and gold cufflinks" }, "description": "A pair of cufflinks with inset alexandrites.", "color": "green" }, @@ -427,14 +427,14 @@ "id": "ruby_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "ruby and gold cufflinks" }, + "name": { "str_sp": "ruby and gold cufflinks" }, "description": "A pair of cufflinks with inset rubies." }, { "id": "peridot_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "peridot and gold cufflinks" }, + "name": { "str_sp": "peridot and gold cufflinks" }, "description": "A pair of cufflinks with inset peridots.", "color": "light_green" }, @@ -442,7 +442,7 @@ "id": "sapphire_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "sapphire and gold cufflinks" }, + "name": { "str_sp": "sapphire and gold cufflinks" }, "description": "A pair of cufflinks with inset sapphires.", "color": "blue" }, @@ -450,7 +450,7 @@ "id": "tourmaline_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "tourmaline and gold cufflinks" }, + "name": { "str_sp": "tourmaline and gold cufflinks" }, "description": "A pair of cufflinks with inset tourmalines.", "color": "light_red" }, @@ -458,7 +458,7 @@ "id": "citrine_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "citrine and gold cufflinks" }, + "name": { "str_sp": "citrine and gold cufflinks" }, "description": "A pair of cufflinks with inset citrines.", "color": "yellow" }, @@ -466,7 +466,7 @@ "id": "blue_topaz_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "blue topaz and gold cufflinks" }, + "name": { "str_sp": "blue topaz and gold cufflinks" }, "description": "A pair of cufflinks with inset blue topaz.", "color": "light_blue" }, @@ -474,7 +474,7 @@ "id": "opal_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "opal and gold cufflinks" }, + "name": { "str_sp": "opal and gold cufflinks" }, "description": "A pair of cufflinks with inset opals.", "color": "white" }, @@ -482,14 +482,14 @@ "id": "pearl_gold_cufflinks", "copy-from": "garnet_gold_cufflinks", "type": "ARMOR", - "name": { "str": "pearl and gold cufflinks" }, + "name": { "str_sp": "pearl and gold cufflinks" }, "description": "A pair of cufflinks with inset pearls.", "color": "white" }, { "id": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "garnet and silver cufflinks" }, + "name": { "str_sp": "garnet and silver cufflinks" }, "description": "A pair of cufflinks with inset garnets.", "weight": "15 g", "volume": 0, @@ -505,7 +505,7 @@ "id": "diamond_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "diamond and silver cufflinks" }, + "name": { "str_sp": "diamond and silver cufflinks" }, "description": "A pair of cufflinks with inset diamonds.", "material": [ "silver", "diamond" ], "color": "white" @@ -514,7 +514,7 @@ "id": "amethyst_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "amethyst and silver cufflinks" }, + "name": { "str_sp": "amethyst and silver cufflinks" }, "description": "A pair of cufflinks with inset amethysts.", "color": "blue" }, @@ -522,7 +522,7 @@ "id": "aquamarine_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "aquamarine and silver cufflinks" }, + "name": { "str_sp": "aquamarine and silver cufflinks" }, "description": "A pair of cufflinks with inset aquamarines.", "color": "light_blue" }, @@ -530,7 +530,7 @@ "id": "emerald_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "emerald and silver cufflinks" }, + "name": { "str_sp": "emerald and silver cufflinks" }, "description": "A pair of cufflinks with inset emeralds.", "color": "green" }, @@ -538,7 +538,7 @@ "id": "alexandrite_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "alexandrite and silver cufflinks" }, + "name": { "str_sp": "alexandrite and silver cufflinks" }, "description": "A pair of cufflinks with inset alexandrites.", "color": "green" }, @@ -546,14 +546,14 @@ "id": "ruby_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "ruby and silver cufflinks" }, + "name": { "str_sp": "ruby and silver cufflinks" }, "description": "A pair of cufflinks with inset rubies." }, { "id": "peridot_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "peridot and silver cufflinks" }, + "name": { "str_sp": "peridot and silver cufflinks" }, "description": "A pair of cufflinks with inset peridots.", "color": "light_green" }, @@ -561,7 +561,7 @@ "id": "sapphire_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "sapphire and silver cufflinks" }, + "name": { "str_sp": "sapphire and silver cufflinks" }, "description": "A pair of cufflinks with inset sapphires.", "color": "blue" }, @@ -569,7 +569,7 @@ "id": "tourmaline_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "tourmaline and silver cufflinks" }, + "name": { "str_sp": "tourmaline and silver cufflinks" }, "description": "A pair of cufflinks with inset tourmalines.", "color": "light_red" }, @@ -577,7 +577,7 @@ "id": "citrine_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "citrine and silver cufflinks" }, + "name": { "str_sp": "citrine and silver cufflinks" }, "description": "A pair of cufflinks with inset citrines.", "color": "yellow" }, @@ -585,7 +585,7 @@ "id": "blue_topaz_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "blue topaz and silver cufflinks" }, + "name": { "str_sp": "blue topaz and silver cufflinks" }, "description": "A pair of cufflinks with inset blue topaz.", "color": "light_blue" }, @@ -593,7 +593,7 @@ "id": "opal_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "opal and silver cufflinks" }, + "name": { "str_sp": "opal and silver cufflinks" }, "description": "A pair of cufflinks with inset opals.", "color": "white" }, @@ -601,14 +601,14 @@ "id": "pearl_silver_cufflinks", "copy-from": "garnet_silver_cufflinks", "type": "ARMOR", - "name": { "str": "pearl and silver cufflinks" }, + "name": { "str_sp": "pearl and silver cufflinks" }, "description": "A pair of cufflinks with inset pearls.", "color": "white" }, { "id": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "garnet and platinum cufflinks" }, + "name": { "str_sp": "garnet and platinum cufflinks" }, "description": "A pair of cufflinks with inset garnets.", "weight": "15 g", "volume": 0, @@ -624,7 +624,7 @@ "id": "diamond_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "diamond and platinum cufflinks" }, + "name": { "str_sp": "diamond and platinum cufflinks" }, "description": "A pair of cufflinks with inset diamonds.", "material": [ "platinum", "diamond" ], "color": "white" @@ -633,7 +633,7 @@ "id": "amethyst_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "amethyst and platinum cufflinks" }, + "name": { "str_sp": "amethyst and platinum cufflinks" }, "description": "A pair of cufflinks with inset amethysts.", "color": "blue" }, @@ -641,7 +641,7 @@ "id": "aquamarine_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "aquamarine and platinum cufflinks" }, + "name": { "str_sp": "aquamarine and platinum cufflinks" }, "description": "A pair of cufflinks with inset aquamarines.", "color": "light_blue" }, @@ -649,7 +649,7 @@ "id": "emerald_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "emerald and platinum cufflinks" }, + "name": { "str_sp": "emerald and platinum cufflinks" }, "description": "A pair of cufflinks with inset emeralds.", "color": "green" }, @@ -657,7 +657,7 @@ "id": "alexandrite_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "alexandrite and platinum cufflinks" }, + "name": { "str_sp": "alexandrite and platinum cufflinks" }, "description": "A pair of cufflinks with inset alexandrites.", "color": "green" }, @@ -665,14 +665,14 @@ "id": "ruby_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "ruby and platinum cufflinks" }, + "name": { "str_sp": "ruby and platinum cufflinks" }, "description": "A pair of cufflinks with inset rubies." }, { "id": "peridot_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "peridot and platinum cufflinks" }, + "name": { "str_sp": "peridot and platinum cufflinks" }, "description": "A pair of cufflinks with inset peridots.", "color": "light_green" }, @@ -680,7 +680,7 @@ "id": "sapphire_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "sapphire and platinum cufflinks" }, + "name": { "str_sp": "sapphire and platinum cufflinks" }, "description": "A pair of cufflinks with inset sapphires.", "color": "blue" }, @@ -688,7 +688,7 @@ "id": "tourmaline_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "tourmaline and platinum cufflinks" }, + "name": { "str_sp": "tourmaline and platinum cufflinks" }, "description": "A pair of cufflinks with inset tourmalines.", "color": "light_red" }, @@ -696,7 +696,7 @@ "id": "citrine_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "citrine and platinum cufflinks" }, + "name": { "str_sp": "citrine and platinum cufflinks" }, "description": "A pair of cufflinks with inset citrines.", "color": "yellow" }, @@ -704,7 +704,7 @@ "id": "blue_topaz_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "blue topaz and platinum cufflinks" }, + "name": { "str_sp": "blue topaz and platinum cufflinks" }, "description": "A pair of cufflinks with inset blue topaz.", "color": "light_blue" }, @@ -712,7 +712,7 @@ "id": "opal_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "opal and platinum cufflinks" }, + "name": { "str_sp": "opal and platinum cufflinks" }, "description": "A pair of cufflinks with inset opals.", "color": "white" }, @@ -720,7 +720,7 @@ "id": "pearl_platinum_cufflinks", "copy-from": "garnet_platinum_cufflinks", "type": "ARMOR", - "name": { "str": "pearl and platinum cufflinks" }, + "name": { "str_sp": "pearl and platinum cufflinks" }, "description": "A pair of cufflinks with inset pearls.", "color": "white" }, diff --git a/data/json/items/armor/pets_horse_armor.json b/data/json/items/armor/pets_horse_armor.json index 372ac4ba882b6..8101abec65a0d 100644 --- a/data/json/items/armor/pets_horse_armor.json +++ b/data/json/items/armor/pets_horse_armor.json @@ -72,7 +72,7 @@ "id": "leather_armor_horse", "copy-from": "horse_armor", "color": "green", - "name": { "str": "boiled leather horse barding with caprison" }, + "name": { "str": "boiled leather horse barding with caprison", "str_pl": "boiled leather horse bardings with caprison" }, "description": "A full barding for horses consisting of boiled leather and cloth undercovering. This caparison is depicting a battle between a monstrous dragon and regal griffin. You could put this on a friendly horse.", "price": 30000, "price_postapoc": 3000, diff --git a/data/json/items/chemicals_and_resources.json b/data/json/items/chemicals_and_resources.json index 9ea495ce9193b..42f380375b78e 100644 --- a/data/json/items/chemicals_and_resources.json +++ b/data/json/items/chemicals_and_resources.json @@ -950,8 +950,7 @@ "category": "chems", "price": 7500, "price_postapoc": 2000, - "name": "composition b", - "name_plural": "composition b", + "name": { "str_sp": "composition b" }, "symbol": "=", "color": "brown", "description": "Composition B is an explosive consisting of castable mixtures of RDX and TNT. It is used as the main explosive filling in artillery projectiles, rockets, land mines, hand grenades and various other munitions.", diff --git a/data/json/items/comestibles/alcohol.json b/data/json/items/comestibles/alcohol.json index 08191ca447041..8a483edbad1fa 100644 --- a/data/json/items/comestibles/alcohol.json +++ b/data/json/items/comestibles/alcohol.json @@ -1178,7 +1178,7 @@ { "type": "COMESTIBLE", "id": "drink_hobo", - "name": "fancy hobo", + "name": { "str_sp": "fancy hobo" }, "weight": "50 g", "color": "yellow", "addiction_type": "alcohol", @@ -1206,7 +1206,7 @@ { "type": "COMESTIBLE", "id": "drink_kalimotxo", - "name": "kalimotxo", + "name": { "str_sp": "kalimotxo" }, "weight": "250 g", "color": "red", "addiction_type": "alcohol", @@ -1234,7 +1234,7 @@ { "type": "COMESTIBLE", "id": "drink_beeknees", - "name": { "str": "bee's knees" }, + "name": { "str_sp": "bee's knees" }, "weight": "248 g", "color": "yellow", "addiction_type": "alcohol", diff --git a/data/json/items/comestibles/carnivore.json b/data/json/items/comestibles/carnivore.json index bdbbcbc852bfe..c11ced48f89de 100644 --- a/data/json/items/comestibles/carnivore.json +++ b/data/json/items/comestibles/carnivore.json @@ -3,7 +3,7 @@ "abstract": "flesh", "type": "COMESTIBLE", "comestible_type": "FOOD", - "name": "meat/fish", + "name": { "str_sp": "meat/fish" }, "material": "flesh", "symbol": "%", "color": "red", diff --git a/data/json/items/comestibles/meat_dishes.json b/data/json/items/comestibles/meat_dishes.json index 54b43145f3934..7421cae980224 100644 --- a/data/json/items/comestibles/meat_dishes.json +++ b/data/json/items/comestibles/meat_dishes.json @@ -108,7 +108,7 @@ { "type": "COMESTIBLE", "id": "royal_beef", - "name": "royal beef", + "name": { "str_sp": "royal beef" }, "weight": "446 g", "color": "white", "spoils_in": "3 days 8 hours", @@ -197,7 +197,7 @@ { "type": "COMESTIBLE", "id": "glazed_tenderloin", - "name": "glazed tenderloins", + "name": { "str_sp": "glazed tenderloins" }, "conditional_names": [ { "type": "COMPONENT_ID", "condition": "mutant", "name": { "str_sp": "grisly %s" } } ], "weight": "205 g", "color": "brown", @@ -437,7 +437,7 @@ "type": "COMESTIBLE", "id": "debug_nutrition", "copy-from": "can_spam", - "name": "holy SPAM of debugging", + "name": { "str": "holy SPAM of debugging", "str_pl": "holy SPAMs of debugging" }, "calories": 2100, "description": "A mysterious lump of SPAM that contains just enough calories and vitamins to feed you for a day. For debug use only.", "//": "This is used for the all_nutrient_starve_test.", diff --git a/data/json/items/comestibles/offal_dishes.json b/data/json/items/comestibles/offal_dishes.json index 6a8186ef43219..e97fc01bef300 100644 --- a/data/json/items/comestibles/offal_dishes.json +++ b/data/json/items/comestibles/offal_dishes.json @@ -275,8 +275,7 @@ "id": "sausage_casings", "copy-from": "spice", "type": "COMESTIBLE", - "name": "sausage casing", - "name_plural": "sausage casings", + "name": { "str": "sausage casing" }, "description": "Sausage casings made from animal intestines. Ready to be used for forming meat products.", "color": "red", "material": "flesh", @@ -285,8 +284,7 @@ { "type": "COMESTIBLE", "id": "homemade_hotdogs", - "name": "homemade hot dog", - "name_plural": "homemade hot dogs", + "name": { "str": "homemade hot dog" }, "copy-from": "hotdogs_frozen" } ] diff --git a/data/json/items/comestibles/other.json b/data/json/items/comestibles/other.json index e0226d1711ac3..173b9a0f65c50 100644 --- a/data/json/items/comestibles/other.json +++ b/data/json/items/comestibles/other.json @@ -449,6 +449,26 @@ "vitamins": [ [ "calcium", 4 ], [ "iron", 47 ], [ "vitC", 7 ] ], "fun": -10 }, + { + "type": "COMESTIBLE", + "id": "foodplace_food", + "name": { "str_sp": "Foodplace's delicious food™" }, + "weight": "500 g", + "color": "magenta", + "comestible_type": "FOOD", + "container": "box_small", + "symbol": "f", + "calories": 500, + "description": "The best-seller from Foodplace, delicious food™, is made with real foodstuff and is guaranteed 100% edible!", + "price": 500, + "price_postapoc": 1000, + "material": "foodplace_foodstuff", + "volume": "500 ml", + "flags": [ "EDIBLE_FROZEN", "IRREPLACEABLE_CONSUMABLE" ], + "addiction_potential": 1, + "charges": 4, + "fun": 2 + }, { "type": "COMESTIBLE", "id": "lentils_cooked", diff --git a/data/json/items/comestibles/seed.json b/data/json/items/comestibles/seed.json index 825a9b5cee95e..18505e1cb9030 100644 --- a/data/json/items/comestibles/seed.json +++ b/data/json/items/comestibles/seed.json @@ -21,7 +21,7 @@ "abstract": "seed_fruit", "type": "COMESTIBLE", "copy-from": "seed", - "name": "fruit seeds", + "name": { "str_sp": "fruit seeds" }, "primary_material": "dried_vegetable", "material": "fruit" }, diff --git a/data/json/items/comestibles/soup.json b/data/json/items/comestibles/soup.json index 9731fdc94f5ad..4be833fae3308 100644 --- a/data/json/items/comestibles/soup.json +++ b/data/json/items/comestibles/soup.json @@ -126,8 +126,7 @@ { "type": "COMESTIBLE", "id": "curry_veggy", - "name": "curry", - "name_plural": "curries", + "name": { "str": "curry", "str_pl": "curries" }, "weight": "263 g", "color": "red", "spoils_in": "5 days", @@ -151,8 +150,7 @@ { "type": "COMESTIBLE", "id": "curry_meat", - "name": "curry with meat", - "name_plural": "curries with meat", + "name": { "str": "curry with meat", "str_pl": "curries with meat" }, "conditional_names": [ { "type": "COMPONENT_ID", "condition": "mutant", "name": { "str": "creature curry", "str_pl": "creature curries" } } ], "weight": "289 g", "color": "red", @@ -274,8 +272,7 @@ { "type": "COMESTIBLE", "id": "soup_dumplings", - "name": "chicken and dumplings", - "name_plural": "chicken and dumplings", + "name": { "str_sp": "chicken and dumplings" }, "weight": "263 g", "color": "light_gray", "spoils_in": "6 days 16 hours", diff --git a/data/json/items/comestibles/veggy_dishes.json b/data/json/items/comestibles/veggy_dishes.json index a4651d467e3d4..6219a761d0be6 100644 --- a/data/json/items/comestibles/veggy_dishes.json +++ b/data/json/items/comestibles/veggy_dishes.json @@ -470,7 +470,7 @@ { "type": "COMESTIBLE", "id": "sauce_pesto", - "name": "pesto", + "name": { "str_sp": "pesto" }, "weight": "65 g", "color": "light_green", "spoils_in": 144, @@ -694,7 +694,7 @@ { "type": "COMESTIBLE", "id": "salsify_baked", - "name": "roasted salsify", + "name": { "str": "roasted salsify", "str_pl": "roasted salsifies" }, "copy-from": "salsify_raw", "spoils_in": "2 days", "healthy": 2, diff --git a/data/json/items/fuel.json b/data/json/items/fuel.json index 9b3b831e45ae6..a914a44edfdc2 100644 --- a/data/json/items/fuel.json +++ b/data/json/items/fuel.json @@ -70,8 +70,7 @@ { "id": "jp8", "type": "AMMO", - "name": "JP8 fuel", - "name_plural": "JP8 fuel", + "name": { "str_sp": "JP8 fuel" }, "description": "A kerosene-based fuel used mainly by US military vehicles as a replacement for diesel and jet fuel, to simplify logistics.", "category": "fuel", "weight": "1 g", @@ -99,8 +98,7 @@ { "id": "avgas", "type": "AMMO", - "name": "avgas fuel", - "name_plural": "avgas fuel", + "name": { "str_sp": "avgas fuel" }, "description": "A specialized type of petroleum-based fuel used to power aircraft.", "category": "fuel", "weight": "1 g", diff --git a/data/json/items/generic.json b/data/json/items/generic.json index 28bcd2035769e..d1c62150a9b2c 100644 --- a/data/json/items/generic.json +++ b/data/json/items/generic.json @@ -295,7 +295,8 @@ "material": [ "steel" ], "techniques": [ "WRAP" ], "volume": "1 L", - "bashing": 12, + "bashing": 26, + "to_hit": -2, "price": 8000, "price_postapoc": 50 }, @@ -2967,6 +2968,21 @@ "use_action": "DISASSEMBLE", "flags": [ "NO_REPAIR" ] }, + { + "id": "premium_survival_kit", + "type": "GENERIC", + "category": "tools", + "name": { "str": "survival kit" }, + "description": "The ultimate survival kit purchased either by the wealthy or the dedicated urban survivalist. It contains tools and items to help you survive in case of an emergency. Disassemble to get its contents.", + "weight": "1612 g", + "volume": "1 L", + "price": 15000, + "material": "aluminum", + "symbol": "!", + "color": "green", + "use_action": { "type": "unpack", "group": "premium_contents", "items_fit": true, "filthy_volume_threshold": "10 L" }, + "flags": [ "NO_REPAIR" ] + }, { "id": "plastic_six_dice", "type": "GENERIC", diff --git a/data/json/items/generic/music.json b/data/json/items/generic/music.json index cfaf28be20f5b..de36fcb0c9251 100644 --- a/data/json/items/generic/music.json +++ b/data/json/items/generic/music.json @@ -29,7 +29,7 @@ { "type": "GENERIC", "id": "headphones_circumaural", - "name": { "str": "headphones" }, + "name": { "str_sp": "headphones" }, "description": "Typical headphones that cover your ears. A well-known brand that is very high quality, with a detachable 1/8\" cable. Comes with a 1/8\" to 1/4\" adaptor.", "symbol": "Ω", "volume": "400 ml", diff --git a/data/json/items/gun/40x53mm.json b/data/json/items/gun/40x53mm.json index 1cf67a7abf318..c312f5f9657dc 100644 --- a/data/json/items/gun/40x53mm.json +++ b/data/json/items/gun/40x53mm.json @@ -28,7 +28,7 @@ [ "rail mount", 1 ], [ "underbarrel mount", 1 ] ], - "modes": [ [ "DEFAULT", "semi-auto", 1, "NPC_AVOID" ] ], + "modes": [ [ "DEFAULT", "semi-auto", 1, "NPC_AVOID" ], [ "AUTO", "auto", 2, "NPC_AVOID" ] ], "magazines": [ [ "40x53mm", [ "belt40mm" ] ] ], "flags": [ "MOUNTED_GUN" ] } diff --git a/data/json/items/melee/bludgeons.json b/data/json/items/melee/bludgeons.json index a482bd0302df4..997d7bf51a3d1 100644 --- a/data/json/items/melee/bludgeons.json +++ b/data/json/items/melee/bludgeons.json @@ -9,7 +9,7 @@ "volume": "3750 ml", "price": 25000, "price_postapoc": 3000, - "bashing": 40, + "bashing": 50, "material": [ "wood", "steel" ], "symbol": "\\", "color": "dark_gray", @@ -26,7 +26,7 @@ "volume": "3750 ml", "price": 4000, "price_postapoc": 1000, - "bashing": 19, + "bashing": 26, "material": [ "wood" ], "symbol": "\\", "color": "brown", @@ -474,13 +474,13 @@ "name": { "str": "homewrecker" }, "description": "A long piece of wood with several chunks of steel firmly tied to it. The resulting weapon is unwieldy and slow but very heavy hitting.", "weight": "3024 g", - "to_hit": -3, + "to_hit": -2, "color": "brown", "symbol": "/", "material": [ "wood", "steel" ], "techniques": [ "WBLOCK_1" ], "volume": "1250 ml", - "bashing": 28, + "bashing": 35, "cutting": 2, "qualities": [ [ "HAMMER", 1 ] ], "flags": [ "STAB", "NONCONDUCTIVE" ], @@ -661,7 +661,7 @@ "flags": [ "BELT_CLIP", "NONCONDUCTIVE" ], "weight": "400 g", "volume": "350 ml", - "bashing": 9, + "bashing": 12, "to_hit": 1, "price_postapoc": 50, "category": "weapons" @@ -689,14 +689,14 @@ "name": { "str": "morningstar" }, "description": "A medieval weapon consisting of a wood handle with a heavy, spiked iron ball on the end. It deals devastating crushing damage, with a small amount of piercing to boot.", "weight": "1400 g", - "to_hit": 1, + "to_hit": -1, "color": "dark_gray", "symbol": "/", "material": [ "iron", "wood" ], "techniques": [ "SWEEP" ], "volume": "1500 ml", - "bashing": 33, - "cutting": 4, + "bashing": 38, + "cutting": 6, "flags": [ "DURABLE_MELEE", "SPEAR", "NONCONDUCTIVE" ], "price": 120000, "price_postapoc": 8000, @@ -708,14 +708,14 @@ "name": { "str": "morningstar" }, "description": "A light, cheaply made replica of a medieval weapon that would normally consist of a wood handle with a heavy, spiked iron ball on the end.", "weight": "700 g", - "to_hit": 1, + "to_hit": -1, "color": "dark_gray", "symbol": "/", "looks_like": "morningstar", "material": [ "aluminum", "wood" ], "techniques": [ "SWEEP" ], "volume": "1500 ml", - "bashing": 8, + "bashing": 26, "cutting": 1, "flags": [ "SPEAR", "NONCONDUCTIVE" ], "price": 12000, @@ -727,14 +727,14 @@ "name": { "str": "morningstar" }, "description": "A medieval weapon consisting of a wood handle with a heavy, spiked iron ball on the end. That end feels lighter than it should.", "weight": "1000 g", - "to_hit": 1, + "to_hit": -1, "color": "dark_gray", "symbol": "/", "looks_like": "morningstar", "material": [ "budget_steel", "wood" ], "techniques": [ "SWEEP" ], "volume": "1500 ml", - "bashing": 11, + "bashing": 26, "cutting": 1, "flags": [ "SPEAR", "NONCONDUCTIVE" ], "price": 12000, @@ -862,7 +862,7 @@ "weight": "1007 g", "volume": "500 ml", "bashing": 8, - "to_hit": 1, + "to_hit": -1, "qualities": [ [ "HAMMER", 1 ] ] }, { diff --git a/data/json/items/melee/fake.json b/data/json/items/melee/fake.json index 4ad3660d34a67..e7b03095c6a23 100644 --- a/data/json/items/melee/fake.json +++ b/data/json/items/melee/fake.json @@ -4,7 +4,7 @@ "id": "bio_claws_weapon", "name": { "str_sp": "bionic claws" }, "description": "Short and sharp claws made from a high-tech metal.", - "to_hit": 4, + "to_hit": -1, "color": "light_gray", "symbol": "{", "material": [ "superalloy" ], diff --git a/data/json/items/melee/unarmed_weapons.json b/data/json/items/melee/unarmed_weapons.json index 07b45ec5f33bf..9d1c5b3fb21b2 100644 --- a/data/json/items/melee/unarmed_weapons.json +++ b/data/json/items/melee/unarmed_weapons.json @@ -5,12 +5,11 @@ "name": { "str_sp": "tiger claws" }, "description": "Also called bagh nakha or iron paw, this is a small claw-like bladed weapon from India designed to be concealed under and against the palm.", "weight": "92 g", - "to_hit": 3, "color": "dark_gray", "symbol": "{", "material": [ "steel" ], - "bashing": 1, - "cutting": 6, + "bashing": 2, + "cutting": 15, "flags": [ "UNARMED_WEAPON", "DURABLE_MELEE" ], "price": 20000, "price_postapoc": 250, @@ -40,7 +39,7 @@ "description": "A metal weapon made of brass, designed to be gripped in the palm and cause punches to do extra damage. A good, quick weapon - but you have to get within punching range to use it.", "material": "brass", "weight": "320 g", - "bashing": 6, + "bashing": 3, "price_postapoc": 250, "flags": [ "UNARMED_WEAPON", "DURABLE_MELEE" ] }, @@ -54,8 +53,8 @@ "material": "steel", "volume": "500 ml", "weight": "1150 g", - "cutting": 16, - "to_hit": 2, + "bashing": 3, + "cutting": 14, "price_postapoc": 500, "qualities": [ [ "CUT", 1 ], [ "BUTCHER", 8 ] ], "flags": [ "UNARMED_WEAPON" ], @@ -71,8 +70,8 @@ "material": "wood", "volume": "250 ml", "weight": "430 g", - "bashing": 4, - "cutting": 6, + "bashing": 3, + "cutting": 4, "price_postapoc": 50, "flags": [ "UNARMED_WEAPON" ] }, @@ -86,7 +85,7 @@ "material": "steel", "volume": "250 ml", "weight": "430 g", - "bashing": 8, + "bashing": 3, "price_postapoc": 50, "qualities": [ [ "HAMMER", 1 ] ], "flags": [ "UNARMED_WEAPON" ] @@ -97,14 +96,14 @@ "name": { "str": "punch dagger" }, "description": "A short and sharp double-edged dagger made to be gripped in the palm, with the blade protruding between the fingers.", "weight": "168 g", - "to_hit": 2, + "to_hit": -1, "price_postapoc": 50, "color": "dark_gray", "symbol": "{", "material": [ "steel" ], "volume": "250 ml", "bashing": 2, - "cutting": 10, + "cutting": 14, "flags": [ "STAB", "UNARMED_WEAPON", "DURABLE_MELEE", "SHEATH_KNIFE" ], "price": 10000, "qualities": [ [ "CUT", 1 ], [ "BUTCHER", 14 ] ] diff --git a/data/json/items/obsolete.json b/data/json/items/obsolete.json index 088833accecb5..2c53e1eab5ba8 100644 --- a/data/json/items/obsolete.json +++ b/data/json/items/obsolete.json @@ -933,7 +933,7 @@ "id": "40mm_flashbang", "copy-from": "40x46mm_grenade", "type": "AMMO", - "name": { "str": "40x46mm " }, + "name": { "str": "40x46mm" }, "description": "A 40mm grenade with a flashbang load. It will detonate with a blast of light and sound, designed to blind, deafen, and disorient anyone nearby.", "extend": { "effects": [ "FLASHBANG" ] } }, diff --git a/data/json/items/resources/metal.json b/data/json/items/resources/metal.json index c9d46782c9d80..2cfeac00b4353 100644 --- a/data/json/items/resources/metal.json +++ b/data/json/items/resources/metal.json @@ -236,7 +236,7 @@ "id": "steel_chunk", "type": "AMMO", "category": "spare_parts", - "name": { "str": "chunk of steel" }, + "name": { "str": "chunk of steel", "str_pl": "chunks of steel" }, "description": "A misshapen chunk of steel. Makes a decent weapon in a pinch, and is also useful for some crafting recipes.", "weight": "250 g", "volume": "250 ml", @@ -256,7 +256,7 @@ "id": "steel_lump", "type": "AMMO", "category": "spare_parts", - "name": { "str": "lump of steel" }, + "name": { "str": "lump of steel", "str_pl": "lumps of steel" }, "description": "A heavy formed piece of steel. Useful for some crafting recipes.", "weight": "1000 g", "volume": "250 ml", diff --git a/data/json/items/vehicle/rotor.json b/data/json/items/vehicle/rotor.json index 972a2640eef03..dab9d3151d805 100644 --- a/data/json/items/vehicle/rotor.json +++ b/data/json/items/vehicle/rotor.json @@ -3,8 +3,7 @@ "id": "heavy_duty_military_rotor", "type": "GENERIC", "category": "veh_parts", - "name": "heavy-duty military rotors", - "name_plural": "sets of heavy-duty military rotors", + "name": { "str": "heavy-duty military rotors", "str_pl": "sets of heavy-duty military rotors" }, "description": "A set of four rotor blades from a military attack helicopter.", "price": 23400, "price_postapoc": 500, @@ -19,8 +18,7 @@ "id": "small_helicopter_rotor", "type": "GENERIC", "category": "veh_parts", - "name": "small civilian helicopter rotors", - "name_plural": "sets of small civilian helicopter rotors", + "name": { "str": "small civilian helicopter rotors", "str_pl": "sets of small civilian helicopter rotors" }, "description": "A set of four rotor blades from a civilian light helicopter.", "price": 1200, "price_postapoc": 250, diff --git a/data/json/martialarts.json b/data/json/martialarts.json index e8ad9d1a73078..5320805b028b9 100644 --- a/data/json/martialarts.json +++ b/data/json/martialarts.json @@ -798,7 +798,7 @@ "type": "martial_art", "id": "style_ninjutsu", "name": { "str": "Ninjutsu" }, - "description": "Ninjutsu is a martial art and set of tactics used by ninja in feudal Japan. It focuses on rapid, precise, silent strikes. Ninjutsu is almost entirely silent and does extra damage if on the first attack. It also provides small combat bonuses every time you move.", + "description": "Ninjutsu is a martial art and set of tactics used by ninja in feudal Japan. It focuses on rapid, precise, silent strikes. Ninjutsu is almost entirely silent and does extra damage on the first attack. It also provides small combat bonuses every time you move.", "initiate": [ "You perform a kuji-in mantra with your hands. Rin, Kai, Jin!", "%s performs a series of intricate hand signs." ], "learn_difficulty": 6, "arm_block": 3, diff --git a/data/json/materials.json b/data/json/materials.json index 697d047ddb351..8629d0093d122 100644 --- a/data/json/materials.json +++ b/data/json/materials.json @@ -666,6 +666,12 @@ "cut_dmg_verb": "cut", "burn_data": [ { "fuel": 1, "smoke": 1, "burn": 1 }, { "fuel": 1, "smoke": 1, "burn": 2 }, { "fuel": 1, "smoke": 1, "burn": 3 } ] }, + { + "type": "material", + "ident": "foodplace_foodstuff", + "name": "Foodplace'delicious foodstuff", + "copy-from": "junk" + }, { "type": "material", "ident": "kevlar", diff --git a/data/json/npcs/classes.json b/data/json/npcs/classes.json index b3ff89058e808..044b90061710b 100644 --- a/data/json/npcs/classes.json +++ b/data/json/npcs/classes.json @@ -202,29 +202,6 @@ { "skill": "archery", "bonus": { "rng": [ 0, 3 ] } } ] }, - { - "type": "npc_class", - "id": "NC_ARSONIST", - "name": { "str": "Arsonist" }, - "job_description": "I'm just watching the world burn.", - "traits": [ - { "group": "BG_survival_story_CRIMINAL" }, - { "group": "NPC_starting_traits" }, - { "group": "Appearance_demographics" }, - [ "FELINE_EARS", 100 ] - ], - "bonus_dex": { "rng": [ -2, 0 ] }, - "bonus_int": { "rng": [ -2, 0 ] }, - "bonus_per": { "rng": [ 0, 2 ] }, - "shopkeeper_item_group": "NC_ARSONIST_misc", - "skills": [ - { "skill": "ALL", "level": { "sum": [ { "dice": [ 3, 2 ] }, { "rng": [ 0, -4 ] } ] } }, - { "skill": "gun", "bonus": { "rng": [ 1, 3 ] } }, - { "skill": "pistol", "bonus": { "rng": [ 1, 3 ] } }, - { "skill": "throw", "bonus": { "rng": [ 0, 2 ] } }, - { "skill": "barter", "bonus": { "rng": [ 2, 4 ] } } - ] - }, { "type": "npc_class", "id": "NC_HUNTER", diff --git a/data/json/npcs/missiondef.json b/data/json/npcs/missiondef.json index 22c4b44ea25a2..2263ca9447a49 100644 --- a/data/json/npcs/missiondef.json +++ b/data/json/npcs/missiondef.json @@ -577,6 +577,17 @@ "start": "find_safety", "origins": [ "ORIGIN_NULL" ] }, + { + "id": "MISSION_LAST_DELIVERY", + "type": "mission_definition", + "name": { "str": "Reach The Mansion And Finish This Delivery" }, + "goal": "MGOAL_GO_TO_TYPE", + "destination": "mansion_c3_north", + "difficulty": 1, + "value": 0, + "start": { "assign_mission_target": { "om_terrain": "mansion_c3", "om_special": "Mansion_Wild", "search_range": 200 } }, + "origins": [ "ORIGIN_GAME_START" ] + }, { "id": "MISSION_RECOVER_PRIEST_DIARY", "type": "mission_definition", diff --git a/data/json/npcs/refugee_center/surface_visitors/NPC_arsonist.json b/data/json/npcs/refugee_center/surface_visitors/NPC_arsonist.json index 0b4557ec07d22..533cffbc14268 100644 --- a/data/json/npcs/refugee_center/surface_visitors/NPC_arsonist.json +++ b/data/json/npcs/refugee_center/surface_visitors/NPC_arsonist.json @@ -10,7 +10,32 @@ "attitude": 0, "mission": 3, "chat": "TALK_ARSONIST", - "faction": "no_faction" + "faction": "no_faction", + "mission_offered": "MISSION_ARSONIST_1_AMMONIUM_NITRATE" + }, + { + "type": "npc_class", + "id": "NC_ARSONIST", + "name": { "str": "Arsonist" }, + "job_description": "I'm just watching the world burn.", + "traits": [ + { "group": "BG_survival_story_CRIMINAL" }, + { "group": "NPC_starting_traits" }, + { "group": "Appearance_demographics" }, + [ "FELINE_EARS", 100 ] + ], + "bonus_dex": { "rng": [ -2, 0 ] }, + "bonus_int": { "rng": [ -2, 0 ] }, + "bonus_per": { "rng": [ 0, 2 ] }, + "shopkeeper_item_group": "NC_ARSONIST_STOCK", + "carry_override": "NC_ARSONIST_STOCK", + "skills": [ + { "skill": "ALL", "level": { "sum": [ { "dice": [ 3, 2 ] }, { "rng": [ 0, -4 ] } ] } }, + { "skill": "gun", "bonus": { "rng": [ 1, 3 ] } }, + { "skill": "pistol", "bonus": { "rng": [ 1, 3 ] } }, + { "skill": "throw", "bonus": { "rng": [ 0, 2 ] } }, + { "skill": "barter", "bonus": { "rng": [ 2, 4 ] } } + ] }, { "type": "talk_topic", @@ -25,8 +50,13 @@ { "text": "What are you doing here?", "topic": "TALK_ARSONIST_DOING" }, { "text": "Heard anything about the outside world?", "topic": "TALK_ARSONIST_WORLD" }, { "text": "Is there any way I can join your group?", "topic": "TALK_ARSONIST_JOIN" }, + { "text": "Do you have any jobs for me?", "topic": "TALK_MISSION_LIST" }, { "text": "What's with your ears?", "topic": "TALK_ARSONIST_MUTATION" }, - { "text": "Anything I can help with?", "topic": "TALK_MISSION_LIST" }, + { + "text": "How are you doing these days?", + "condition": { "u_has_var": "TALK_ARSONIST_SUPPLIED", "type": "talk", "context": "flag", "value": "yes" }, + "topic": "TALK_ARSONIST_TRADING" + }, { "text": "Well, bye.", "topic": "TALK_DONE" } ] }, @@ -79,12 +109,47 @@ { "type": "talk_topic", "id": "TALK_ARSONIST_DOING", - "dynamic_line": "I burn down buildings and sell the Free Merchants the materials. No, seriously. If you've seen burned wreckage in place of suburbs or even see the pile of rebar for sale, that's probably me. They've kept me well off in exchange, I guess. I'll sell you a Molotov Cocktail or two, if you want.", + "dynamic_line": "I burn down buildings and sell the Free Merchants the materials. No, seriously. If you've seen burned wreckage in place of suburbs or even see the pile of rebar for sale, that's probably me. They've kept me well off in exchange, I guess.", "responses": [ { "text": "I'll buy.", "effect": "start_trade", "topic": "TALK_ARSONIST" }, { "text": "Who needs rebar?", "topic": "TALK_ARSONIST_DOING_REBAR" } ] }, + { + "id": "MISSION_ARSONIST_1_AMMONIUM_NITRATE", + "type": "mission_definition", + "name": { "str": "Supply the arsonist." }, + "description": "Bring the arsonist 42 kg of commercial fertilizer", + "difficulty": 1, + "value": 500, + "origins": [ "ORIGIN_SECONDARY" ], + "goal": "MGOAL_FIND_ITEM", + "item": "fertilizer_commercial", + "count": 120, + "dialogue": { + "describe": "I could use some help getting some materials.", + "offer": "I could use some help getting some materials. Molotovs are nice for burning down buildings but aren't all that for keeping yourself safe. If you could get me two bags of commercial fertilizer I could make something a lot more potent.", + "accepted": "Oh man, thanks so much friend. You won't regret it.", + "rejected": "Think it over.", + "advice": "Commercial fertilizer tends to be made from ammonium nitrate, which is also usable as an explosive. Try looking for some around the abandoned farms.", + "inquire": "Did you find any fertilizer? Are you sure this is the ammonium nitrate kind?", + "success": "This is great! I'll get to work making something of this. You can have some of my Molotovs, I won't need quite so many now.", + "success_lie": "I guess I could convince the shelter to sell me some.", + "failure": "Damn. Perhaps I wasn't the only one who thought of this." + }, + "end": { + "effect": [ + { "u_buy_item": "molotov", "count": 10 }, + { "u_add_var": "TALK_ARSONIST_SUPPLIED", "type": "talk", "context": "flag", "value": "yes" } + ] + } + }, + { + "type": "talk_topic", + "id": "TALK_ARSONIST_TRADING", + "dynamic_line": "I made some nice things with that ammonium nitrate you got me. Want to trade?", + "responses": [ { "text": "I'll buy.", "effect": "start_trade", "topic": "TALK_ARSONIST" } ] + }, { "type": "talk_topic", "id": "TALK_ARSONIST_MUTATION_INSULT", diff --git a/data/json/overmap/overmap_special/specials.json b/data/json/overmap/overmap_special/specials.json index 1eeb706c27fe7..cc3bc54184d03 100644 --- a/data/json/overmap/overmap_special/specials.json +++ b/data/json/overmap/overmap_special/specials.json @@ -221,8 +221,8 @@ ], "connections": [ { "point": [ 0, -1, 0 ], "terrain": "road", "existing": true } ], "locations": [ "land", "swamp" ], - "city_distance": [ 10, 200 ], - "city_sizes": [ 1, 3 ], + "city_distance": [ 20, -1 ], + "city_sizes": [ 1, 8 ], "occurrences": [ 0, 2 ], "flags": [ "CLASSIC", "WILDERNESS" ] }, diff --git a/data/json/professions.json b/data/json/professions.json index 26bd20578a3ea..bbcb310c9d704 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -551,7 +551,10 @@ { "level": 1, "name": "melee" }, { "level": 1, "name": "throw" }, { "level": 2, "name": "archery" }, - { "level": 2, "name": "survival" } + { "level": 3, "name": "survival" }, + { "level": 1, "name": "cooking" }, + { "level": 1, "name": "fabrication" }, + { "level": 1, "name": "tailor" } ], "traits": [ "PROF_CHURL" ] }, diff --git a/data/json/scenarios.json b/data/json/scenarios.json index c08fa362e2831..a0312f178ec3f 100644 --- a/data/json/scenarios.json +++ b/data/json/scenarios.json @@ -172,12 +172,12 @@ "type": "scenario", "ident": "medieval", "name": "Challenge - Medieval Peasant", - "points": -6, + "points": -8, "description": "Som nigromancie hath brought yow hidder! Ye have only the hoose on youre legges and the knyf at youre syde and youre prayeres to Marie moder of God.", "start_name": "Wilderness", "allowed_locs": [ "sloc_forest", "sloc_field" ], "professions": [ "churl" ], - "forced_traits": [ "ILLITERATE", "ANTIJUNK", "STRONGSTOMACH" ], + "forced_traits": [ "ILLITERATE", "ANTIJUNK", "STRONGSTOMACH", "WAYFARER", "SPIRITUAL" ], "forbidden_traits": [ "FASTREADER", "SLOWREADER" ], "flags": [ "CHALLENGE", "LONE_START" ] }, @@ -418,12 +418,25 @@ "ident": "foodplace", "name": "The Mascot Rises", "points": 0, - "description": "You just finished your shift and got back in the break room when you heard the alarms and the security door shutting down behind you. There's a lot of customers out there and you're not sure Foodplace delicious food is going to be enough for them.", + "description": "You just finished your shift and got back in the break room when you heard the alarms and the security door shutting down behind you. There's a lot of customers out there and you're not sure Foodplace's delicious food™ is going to be enough for them.", "allowed_locs": [ "sloc_restaraunt_foodplace_break_room" ], "professions": [ "true_foodperson", "unemployed" ], "start_name": "Foodplace Break Room", "flags": [ "CITY_START" ] }, + { + "type": "scenario", + "ident": "last_delivery", + "name": "The Last Delivery", + "points": 2, + "description": "While the world was falling apart someone called to order some of Foodplace's delicious food™ and they sent you to do the delivery. You're not sure about much, but one thing is certain: that delicious food™ is going to get delivered even if that's the last thing you do!", + "vehicle": "food_truck_delivery_mission", + "professions": [ "true_foodperson", "unemployed" ], + "start_name": "A Stop On The Road", + "allowed_locs": [ "sloc_gas_station" ], + "missions": [ "MISSION_LAST_DELIVERY" ], + "flags": [ "LONE_START" ] + }, { "type": "scenario", "ident": "wilderness", diff --git a/data/json/scores.json b/data/json/scores.json index 961089f99bc72..fb0565d91471a 100644 --- a/data/json/scores.json +++ b/data/json/scores.json @@ -30,7 +30,8 @@ "id": "num_avatar_kills", "type": "event_statistic", "stat_type": "count", - "event_transformation": "avatar_kills" + "event_transformation": "avatar_kills", + "description": "Number of monsters killed" }, { "id": "num_avatar_zombie_kills", @@ -42,15 +43,8 @@ { "id": "score_kills", "type": "score", - "description": "Number of monsters killed: %s", "statistic": "num_avatar_kills" }, - { - "id": "achievement_kill_zombie", - "type": "achievement", - "description": "One down, billions to go\u2026", - "requirements": [ { "event_statistic": "num_avatar_zombie_kills", "is": ">=", "target": 1 } ] - }, { "id": "moves_not_mounted", "type": "event_transformation", diff --git a/data/json/start_locations.json b/data/json/start_locations.json index 84a946d34e701..a1055c362b678 100644 --- a/data/json/start_locations.json +++ b/data/json/start_locations.json @@ -393,6 +393,12 @@ "name": "Lake Cabin", "terrain": [ "cabin_lake" ] }, + { + "type": "start_location", + "id": "sloc_gas_station", + "name": "Gas Station", + "terrain": [ "s_gas_rural" ] + }, { "type": "start_location", "id": "sloc_lighthouse_ground", diff --git a/data/json/vehicle_groups.json b/data/json/vehicle_groups.json index a55f56f691d4a..efd1459fe5a36 100644 --- a/data/json/vehicle_groups.json +++ b/data/json/vehicle_groups.json @@ -54,6 +54,7 @@ [ "humvee", 150 ], [ "humvee_gl", 50 ], [ "icecream_truck", 50 ], + [ "food_truck", 50 ], [ "wienermobile", 5 ], [ "tatra_truck", 100 ], [ "4x4_car", 500 ] @@ -236,6 +237,7 @@ [ "motorcycle_sidecart", 300 ], [ "shopping_cart", 1000 ], [ "icecream_truck", 50 ], + [ "food_truck", 20 ], [ "wienermobile", 5 ], [ "portable_generator", 50 ], [ "4x4_car", 200 ] diff --git a/data/json/vehicles/vans_busses.json b/data/json/vehicles/vans_busses.json index 8b2145ac30338..148dafb054178 100644 --- a/data/json/vehicles/vans_busses.json +++ b/data/json/vehicles/vans_busses.json @@ -689,6 +689,345 @@ { "x": -1, "y": 0, "chance": 15, "items": [ "money_bundle" ] } ] }, + { + "id": "food_truck", + "type": "vehicle", + "name": "Food Truck", + "blueprint": [ + [ " o " ], + [ "O---+-O" ], + [ "|&&H#'|" ], + [ "+===='>" ], + [ "|o==#'|" ], + [ "O-#-+-O" ], + [ " o " ] + ], + "parts": [ + { "x": 0, "y": 0, "part": "frame_vertical_2" }, + { "x": 0, "y": 0, "part": "seat" }, + { "x": 0, "y": 0, "part": "seatbelt" }, + { "x": 0, "y": 0, "part": "controls" }, + { "x": 0, "y": 0, "part": "dashboard" }, + { "x": 0, "y": 0, "part": "vehicle_clock" }, + { "x": 0, "y": 0, "part": "vehicle_alarm" }, + { "x": 0, "y": 0, "part": "horn_car" }, + { "x": 0, "y": 0, "part": "roof" }, + { "x": 0, "y": -1, "part": "frame_vertical" }, + { "x": 0, "y": -1, "part": "door" }, + { "x": 0, "y": -1, "part": "roof" }, + { "x": 0, "y": 1, "part": "frame_vertical_2" }, + { "x": 0, "y": 1, "part": "aisle_vertical" }, + { "x": 0, "y": 1, "part": "roof" }, + { "x": 0, "y": 2, "part": "frame_vertical_2" }, + { "x": 0, "y": 2, "part": "seat" }, + { "x": 0, "y": 2, "part": "seatbelt" }, + { "x": 0, "y": 2, "part": "roof" }, + { "x": 0, "y": 3, "part": "frame_vertical" }, + { "x": 0, "y": 3, "part": "door" }, + { "x": 0, "y": 3, "part": "roof" }, + { "x": 1, "y": 0, "part": "frame_vertical_2" }, + { "x": 1, "y": 0, "part": "windshield" }, + { "x": 1, "y": -1, "part": "frame_vertical" }, + { "x": 1, "y": -1, "part": "windshield" }, + { "x": 1, "y": -2, "part": "wing_mirror" }, + { "x": 1, "y": 1, "part": "frame_vertical_2" }, + { "x": 1, "y": 1, "part": "windshield" }, + { "x": 1, "y": 2, "part": "frame_vertical_2" }, + { "x": 1, "y": 2, "part": "windshield" }, + { "x": 1, "y": 3, "part": "frame_vertical" }, + { "x": 1, "y": 3, "part": "windshield" }, + { "x": 1, "y": 4, "part": "wing_mirror" }, + { "x": 2, "y": 0, "part": "frame_horizontal" }, + { "x": 2, "y": 0, "part": "halfboard_horizontal" }, + { "x": 2, "y": -1, "part": "frame_nw" }, + { "x": 2, "y": -1, "part": "halfboard_nw" }, + { "x": 2, "y": -1, "part": "headlight" }, + { "x": 2, "y": -1, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, + { "x": 2, "y": 1, "part": "frame_cover" }, + { "x": 2, "y": 1, "part": "halfboard_cover" }, + { "x": 2, "y": 1, "part": "engine_v6" }, + { "x": 2, "y": 1, "part": "alternator_truck" }, + { "x": 2, "y": 1, "part": "battery_car" }, + { "x": 2, "y": 2, "part": "frame_horizontal" }, + { "x": 2, "y": 2, "part": "halfboard_horizontal" }, + { "x": 2, "y": 3, "part": "frame_ne" }, + { "x": 2, "y": 3, "part": "halfboard_ne" }, + { "x": 2, "y": 3, "part": "headlight" }, + { "x": 2, "y": 3, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, + { "x": -1, "y": 0, "part": "frame_vertical_2" }, + { "x": -1, "y": 0, "part": "minifridge" }, + { "x": -1, "y": 0, "part": "roof" }, + { "x": -1, "y": -1, "part": "frame_vertical" }, + { "x": -1, "y": -1, "part": "board_vertical" }, + { "x": -1, "y": -1, "part": "tank", "fuel": "gasoline" }, + { "x": -1, "y": 1, "part": "frame_vertical_2" }, + { "x": -1, "y": 1, "part": "aisle_vertical" }, + { "x": -1, "y": 1, "part": "roof" }, + { "x": -1, "y": 2, "part": "frame_vertical_2" }, + { "x": -1, "y": 2, "part": "aisle_vertical" }, + { "x": -1, "y": 2, "part": "roof" }, + { "x": -1, "y": 3, "part": "frame_vertical" }, + { "x": -1, "y": 3, "part": "board_vertical" }, + { "x": -2, "y": 0, "part": "frame_vertical_2" }, + { "x": -2, "y": 0, "part": "kitchen_unit" }, + { "x": -2, "y": 0, "part": "roof" }, + { "x": -2, "y": -1, "part": "frame_vertical" }, + { "x": -2, "y": -1, "part": "board_vertical" }, + { "x": -2, "y": 1, "part": "frame_vertical_2" }, + { "x": -2, "y": 1, "part": "aisle_vertical" }, + { "x": -2, "y": 1, "part": "roof" }, + { "x": -2, "y": 2, "part": "frame_vertical_2" }, + { "x": -2, "y": 2, "part": "aisle_vertical" }, + { "x": -2, "y": 2, "part": "roof" }, + { "x": -2, "y": 3, "part": "frame_vertical" }, + { "x": -2, "y": 3, "part": "windshield" }, + { "x": -3, "y": 0, "part": "frame_vertical_2" }, + { "x": -3, "y": 0, "part": "minifreezer" }, + { "x": -3, "y": 0, "part": "roof" }, + { "x": -3, "y": -1, "part": "frame_vertical" }, + { "x": -3, "y": -1, "part": "board_vertical" }, + { "x": -3, "y": 1, "part": "frame_vertical_2" }, + { "x": -3, "y": 1, "part": "aisle_vertical" }, + { "x": -3, "y": 1, "part": "roof" }, + { "x": -3, "y": 2, "part": "frame_vertical_2" }, + { "x": -3, "y": 2, "part": "storage_battery" }, + { "x": -3, "y": 2, "part": "box" }, + { "x": -3, "y": 2, "part": "roof" }, + { "x": -3, "y": 3, "part": "frame_vertical" }, + { "x": -3, "y": 3, "part": "board_vertical" }, + { "x": -4, "y": 0, "part": "frame_horizontal" }, + { "x": -4, "y": 0, "part": "board_horizontal" }, + { "x": -4, "y": 0, "part": "muffler" }, + { "x": -4, "y": 0, "part": "roof" }, + { "x": -4, "y": -1, "part": "frame_sw" }, + { "x": -4, "y": -1, "part": "board_sw" }, + { "x": -4, "y": -1, "parts": [ "wheel_mount_medium", "wheel" ] }, + { "x": -4, "y": -1, "part": "roof" }, + { "x": -4, "y": 1, "part": "frame_horizontal" }, + { "x": -4, "y": 1, "part": "door" }, + { "x": -4, "y": 1, "part": "roof" }, + { "x": -4, "y": 2, "part": "frame_horizontal" }, + { "x": -4, "y": 2, "part": "board_horizontal" }, + { "x": -4, "y": 2, "part": "beeper" }, + { "x": -4, "y": 2, "part": "roof" }, + { "x": -4, "y": 3, "part": "frame_se" }, + { "x": -4, "y": 3, "part": "board_se" }, + { "x": -4, "y": 3, "parts": [ "wheel_mount_medium", "wheel" ] }, + { "x": -4, "y": 3, "part": "roof" } + ], + "items": [ + { "x": -3, "y": 0, "chance": 70, "item_groups": [ "fridgesnacks" ] }, + { "x": -3, "y": 0, "chance": 20, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 20, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 60, "item_groups": [ "fridgesnacks" ] }, + { "x": -3, "y": 0, "chance": 50, "item_groups": [ "fridgesnacks" ] }, + { "x": -3, "y": 0, "chance": 30, "item_groups": [ "fridgesnacks" ] }, + { "x": -1, "y": 0, "chance": 60, "item_groups": [ "fridgesnacks" ] }, + { "x": -1, "y": 0, "chance": 60, "item_groups": [ "fridgesnacks" ] }, + { "x": -1, "y": 0, "chance": 60, "item_groups": [ "fridgesnacks" ] }, + { "x": -1, "y": 0, "chance": 20, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 20, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 60, "item_groups": [ "fridgesnacks" ] }, + { "x": -1, "y": 0, "chance": 70, "item_groups": [ "fast_fridge" ] }, + { "x": -1, "y": 0, "chance": 70, "item_groups": [ "fast_fridge" ] }, + { "x": -1, "y": 0, "chance": 70, "item_groups": [ "fast_fridge" ] }, + { "x": -1, "y": 0, "chance": 70, "item_groups": [ "fast_fridge" ] }, + { "x": -1, "y": 0, "chance": 30, "item_groups": [ "fridgesnacks" ] }, + { "x": -3, "y": 2, "chance": 60, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 70, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 30, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 20, "item_groups": [ "coffee_counter" ] }, + { "x": -3, "y": 2, "chance": 40, "items": [ "ketchup" ] }, + { "x": -3, "y": 2, "chance": 40, "items": [ "mustard" ] }, + { "x": -3, "y": 2, "chance": 40, "items": [ "mayonnaise" ] }, + { "x": 0, "y": 2, "chance": 15, "items": [ "money_bundle" ] }, + { "x": 0, "y": 2, "chance": 100, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 100, "items": [ "months_old_newspaper" ] }, + { "x": 0, "y": 2, "chance": 50, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 50, "items": [ "months_old_newspaper" ] }, + { "x": 0, "y": 2, "chance": 30, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 50, "items": [ "roadmap" ] }, + { "x": 0, "y": 2, "chance": 30, "items": [ "months_old_newspaper" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "foodperson_mask" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "cape_fp" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "chestguard_hard" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "legguard_hard" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "armguard_hard" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "gloves_rubber" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "boots_rubber" ] }, + { "x": -3, "y": 2, "chance": 20, "items": [ "medium_disposable_cell" ] } + ] + }, + { + "//": "This is a duplicate used for the last delivery starting scenario", + "id": "food_truck_delivery_mission", + "type": "vehicle", + "name": "Food Truck", + "blueprint": [ + [ " o " ], + [ "O---+-O" ], + [ "|&&H#'|" ], + [ "+===='>" ], + [ "|o==#'|" ], + [ "O-#-+-O" ], + [ " o " ] + ], + "parts": [ + { "x": 0, "y": 0, "part": "frame_vertical_2" }, + { "x": 0, "y": 0, "part": "seat" }, + { "x": 0, "y": 0, "part": "seatbelt" }, + { "x": 0, "y": 0, "part": "controls" }, + { "x": 0, "y": 0, "part": "dashboard" }, + { "x": 0, "y": 0, "part": "vehicle_clock" }, + { "x": 0, "y": 0, "part": "vehicle_alarm" }, + { "x": 0, "y": 0, "part": "horn_car" }, + { "x": 0, "y": 0, "part": "roof" }, + { "x": 0, "y": -1, "part": "frame_vertical" }, + { "x": 0, "y": -1, "part": "door" }, + { "x": 0, "y": -1, "part": "roof" }, + { "x": 0, "y": 1, "part": "frame_vertical_2" }, + { "x": 0, "y": 1, "part": "aisle_vertical" }, + { "x": 0, "y": 1, "part": "roof" }, + { "x": 0, "y": 2, "part": "frame_vertical_2" }, + { "x": 0, "y": 2, "part": "seat" }, + { "x": 0, "y": 2, "part": "seatbelt" }, + { "x": 0, "y": 2, "part": "roof" }, + { "x": 0, "y": 3, "part": "frame_vertical" }, + { "x": 0, "y": 3, "part": "door" }, + { "x": 0, "y": 3, "part": "roof" }, + { "x": 1, "y": 0, "part": "frame_vertical_2" }, + { "x": 1, "y": 0, "part": "windshield" }, + { "x": 1, "y": -1, "part": "frame_vertical" }, + { "x": 1, "y": -1, "part": "windshield" }, + { "x": 1, "y": -2, "part": "wing_mirror" }, + { "x": 1, "y": 1, "part": "frame_vertical_2" }, + { "x": 1, "y": 1, "part": "windshield" }, + { "x": 1, "y": 2, "part": "frame_vertical_2" }, + { "x": 1, "y": 2, "part": "windshield" }, + { "x": 1, "y": 3, "part": "frame_vertical" }, + { "x": 1, "y": 3, "part": "windshield" }, + { "x": 1, "y": 4, "part": "wing_mirror" }, + { "x": 2, "y": 0, "part": "frame_horizontal" }, + { "x": 2, "y": 0, "part": "halfboard_horizontal" }, + { "x": 2, "y": -1, "part": "frame_nw" }, + { "x": 2, "y": -1, "part": "halfboard_nw" }, + { "x": 2, "y": -1, "part": "headlight" }, + { "x": 2, "y": -1, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, + { "x": 2, "y": 1, "part": "frame_cover" }, + { "x": 2, "y": 1, "part": "halfboard_cover" }, + { "x": 2, "y": 1, "part": "engine_v6" }, + { "x": 2, "y": 1, "part": "alternator_truck" }, + { "x": 2, "y": 1, "part": "battery_car" }, + { "x": 2, "y": 2, "part": "frame_horizontal" }, + { "x": 2, "y": 2, "part": "halfboard_horizontal" }, + { "x": 2, "y": 3, "part": "frame_ne" }, + { "x": 2, "y": 3, "part": "halfboard_ne" }, + { "x": 2, "y": 3, "part": "headlight" }, + { "x": 2, "y": 3, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, + { "x": -1, "y": 0, "part": "frame_vertical_2" }, + { "x": -1, "y": 0, "part": "minifridge" }, + { "x": -1, "y": 0, "part": "roof" }, + { "x": -1, "y": -1, "part": "frame_vertical" }, + { "x": -1, "y": -1, "part": "board_vertical" }, + { "x": -1, "y": -1, "part": "tank", "fuel": "gasoline" }, + { "x": -1, "y": 1, "part": "frame_vertical_2" }, + { "x": -1, "y": 1, "part": "aisle_vertical" }, + { "x": -1, "y": 1, "part": "roof" }, + { "x": -1, "y": 2, "part": "frame_vertical_2" }, + { "x": -1, "y": 2, "part": "aisle_vertical" }, + { "x": -1, "y": 2, "part": "roof" }, + { "x": -1, "y": 3, "part": "frame_vertical" }, + { "x": -1, "y": 3, "part": "board_vertical" }, + { "x": -2, "y": 0, "part": "frame_vertical_2" }, + { "x": -2, "y": 0, "part": "kitchen_unit" }, + { "x": -2, "y": 0, "part": "roof" }, + { "x": -2, "y": -1, "part": "frame_vertical" }, + { "x": -2, "y": -1, "part": "board_vertical" }, + { "x": -2, "y": 1, "part": "frame_vertical_2" }, + { "x": -2, "y": 1, "part": "aisle_vertical" }, + { "x": -2, "y": 1, "part": "roof" }, + { "x": -2, "y": 2, "part": "frame_vertical_2" }, + { "x": -2, "y": 2, "part": "aisle_vertical" }, + { "x": -2, "y": 2, "part": "roof" }, + { "x": -2, "y": 3, "part": "frame_vertical" }, + { "x": -2, "y": 3, "part": "windshield" }, + { "x": -3, "y": 0, "part": "frame_vertical_2" }, + { "x": -3, "y": 0, "part": "minifreezer" }, + { "x": -3, "y": 0, "part": "roof" }, + { "x": -3, "y": -1, "part": "frame_vertical" }, + { "x": -3, "y": -1, "part": "board_vertical" }, + { "x": -3, "y": 1, "part": "frame_vertical_2" }, + { "x": -3, "y": 1, "part": "aisle_vertical" }, + { "x": -3, "y": 1, "part": "roof" }, + { "x": -3, "y": 2, "part": "frame_vertical_2" }, + { "x": -3, "y": 2, "part": "storage_battery" }, + { "x": -3, "y": 2, "part": "box" }, + { "x": -3, "y": 2, "part": "roof" }, + { "x": -3, "y": 3, "part": "frame_vertical" }, + { "x": -3, "y": 3, "part": "board_vertical" }, + { "x": -4, "y": 0, "part": "frame_horizontal" }, + { "x": -4, "y": 0, "part": "board_horizontal" }, + { "x": -4, "y": 0, "part": "muffler" }, + { "x": -4, "y": 0, "part": "roof" }, + { "x": -4, "y": -1, "part": "frame_sw" }, + { "x": -4, "y": -1, "part": "board_sw" }, + { "x": -4, "y": -1, "parts": [ "wheel_mount_medium", "wheel" ] }, + { "x": -4, "y": -1, "part": "roof" }, + { "x": -4, "y": 1, "part": "frame_horizontal" }, + { "x": -4, "y": 1, "part": "door" }, + { "x": -4, "y": 1, "part": "roof" }, + { "x": -4, "y": 2, "part": "frame_horizontal" }, + { "x": -4, "y": 2, "part": "board_horizontal" }, + { "x": -4, "y": 2, "part": "beeper" }, + { "x": -4, "y": 2, "part": "roof" }, + { "x": -4, "y": 3, "part": "frame_se" }, + { "x": -4, "y": 3, "part": "board_se" }, + { "x": -4, "y": 3, "parts": [ "wheel_mount_medium", "wheel" ] }, + { "x": -4, "y": 3, "part": "roof" } + ], + "items": [ + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -1, "y": 0, "chance": 100, "items": [ "foodplace_food" ] }, + { "x": -3, "y": 2, "chance": 20, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 50, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 30, "item_groups": [ "snacks" ] }, + { "x": -3, "y": 2, "chance": 20, "item_groups": [ "coffee_counter" ] }, + { "x": 0, "y": 2, "chance": 100, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 100, "items": [ "months_old_newspaper" ] }, + { "x": 0, "y": 2, "chance": 50, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 50, "items": [ "months_old_newspaper" ] }, + { "x": 0, "y": 2, "chance": 30, "items": [ "flyer" ] }, + { "x": 0, "y": 2, "chance": 70, "items": [ "roadmap" ] }, + { "x": 0, "y": 2, "chance": 30, "items": [ "months_old_newspaper" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "foodperson_mask" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "cape_fp" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "chestguard_hard" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "legguard_hard" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "armguard_hard" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "gloves_rubber" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "boots_rubber" ] }, + { "x": -3, "y": 2, "chance": 100, "items": [ "medium_disposable_cell" ] } + ] + }, { "id": "lux_rv", "type": "vehicle", diff --git a/data/legacy/1/obsolete.json b/data/legacy/1/obsolete.json index 3eb30e04496c7..fd42f56fcd559 100644 --- a/data/legacy/1/obsolete.json +++ b/data/legacy/1/obsolete.json @@ -3,8 +3,7 @@ "id": "reloaded_22_cb", "type": "AMMO", "price": 1800, - "name": "handloaded .22 CB", - "name_plural": "handloaded .22 CB", + "name": { "str_sp": "handloaded .22 CB" }, "symbol": "=", "color": "yellow", "description": "Conical Ball .22 is a variety of .22 ammunition with a very small propellant charge and generally lacks gunpowder. The end result is a subsonic round. It is nearly silent, but is so weak as to be nearly useless. This one has been handmade using an intact casing.", @@ -210,8 +209,7 @@ "category": "spare_parts", "symbol": ",", "color": "light_gray", - "name": "10 plastic bags", - "name_plural": "10 plastic bags", + "name": { "str_sp": "10 plastic bags" }, "description": "10 plastic bags, folded smooth and wrapped tightly together with a string.", "price": 500, "material": "plastic", @@ -280,8 +278,7 @@ "id": "small_charcoal", "category": "spare_parts", "price": 1000, - "name": "charcoal pieces", - "name_plural": "charcoal pieces", + "name": { "str_sp": "charcoal pieces" }, "symbol": "=", "color": "dark_gray", "description": "These are smaller pieces of charcoal used in smaller heating devices.", @@ -298,8 +295,7 @@ "id": "small_coal", "category": "spare_parts", "price": 1000, - "name": "coal pieces", - "name_plural": "coal pieces", + "name": { "str_sp": "coal pieces" }, "symbol": "=", "color": "dark_gray", "description": "These are smaller pieces of coal used in smaller heating devices.", diff --git a/data/legacy/4/boots.json b/data/legacy/4/boots.json index 81bc68d88b280..a405708d7dcb8 100644 --- a/data/legacy/4/boots.json +++ b/data/legacy/4/boots.json @@ -2,8 +2,7 @@ { "id": "boots", "type": "ARMOR", - "name": "pair of boots", - "name_plural": "pairs of boots", + "name": { "str": "pair of boots", "str_pl": "pairs of boots" }, "description": "Tough leather boots. Very durable.", "weight": 1060, "volume": 10, @@ -34,8 +33,7 @@ "id": "boots_bone", "type": "ARMOR", "category": "armor", - "name": "pair of bone armor boots", - "name_plural": "pairs of bone armor boots", + "name": { "str": "pair of bone armor boots", "str_pl": "pairs of bone armor boots" }, "description": "Leather boots armored with reinforcements made from bone. Light and strong.", "weight": 1824, "volume": 17, @@ -66,8 +64,7 @@ "id": "boots_bunker", "type": "ARMOR", "category": "armor", - "name": "pair of turnout boots", - "name_plural": "pairs of turnout boots", + "name": { "str": "pair of turnout boots", "str_pl": "pairs of turnout boots" }, "description": "A pair of steel-toed rubber boots, the sort worn by firefighters. Highly resistant to heat and flame, they provide excellent protection from injury.", "weight": 1930, "volume": 14, @@ -97,8 +94,7 @@ "id": "boots_chitin", "type": "ARMOR", "category": "armor", - "name": "pair of chitinous boots", - "name_plural": "pairs of chitinous boots", + "name": { "str": "pair of chitinous boots", "str_pl": "pairs of chitinous boots" }, "description": "Boots made from the exoskeletons of insects. Light and durable.", "weight": 1620, "volume": 17, @@ -129,8 +125,7 @@ "id": "boots_combat", "type": "ARMOR", "category": "armor", - "name": "pair of combat boots", - "name_plural": "pairs of combat boots", + "name": { "str": "pair of combat boots", "str_pl": "pairs of combat boots" }, "description": "Modern reinforced tactical combat boots. Very durable.", "weight": 1060, "volume": 8, @@ -161,8 +156,7 @@ "id": "boots_fsurvivor", "type": "ARMOR", "category": "armor", - "name": "pair of survivor fireboots", - "name_plural": "pairs of survivor fireboots", + "name": { "str": "pair of survivor fireboots", "str_pl": "pairs of survivor fireboots" }, "description": "A pair of customized, Kevlar armored Nomex boots, modified to provide maximum protection from harm and the elements, even when knee-deep in the dead.", "weight": 1980, "volume": 12, @@ -192,8 +186,7 @@ { "id": "boots_fur", "type": "ARMOR", - "name": "pair of fur boots", - "name_plural": "pairs of fur boots", + "name": { "str": "pair of fur boots", "str_pl": "pairs of fur boots" }, "description": "Boots lined with fur for warmth.", "weight": 1890, "volume": 18, @@ -224,8 +217,7 @@ "id": "boots_h20survivor", "type": "ARMOR", "category": "armor", - "name": "pair of survivor wetsuit boots", - "name_plural": "pairs of survivor wetsuit boots", + "name": { "str": "pair of survivor wetsuit boots", "str_pl": "pairs of survivor wetsuit boots" }, "description": "A pair of customized, Kevlar armored neoprene boots, modified to provide maximum protection from harm and the elements, even when knee-deep in the dead.", "weight": 1180, "volume": 6, @@ -255,8 +247,7 @@ { "id": "boots_hiking", "type": "ARMOR", - "name": "pair of hiking boots", - "name_plural": "pairs of hiking boots", + "name": { "str": "pair of hiking boots", "str_pl": "pairs of hiking boots" }, "description": "Tough yet light leather boots. Durable and comfortable.", "weight": 960, "volume": 8, @@ -287,8 +278,7 @@ "id": "boots_hsurvivor", "type": "ARMOR", "category": "armor", - "name": "pair of heavy survivor boots", - "name_plural": "pairs of heavy survivor boots", + "name": { "str": "pair of heavy survivor boots", "str_pl": "pairs of heavy survivor boots" }, "description": "A pair of customized Kevlar boots, heavily armored with steel and modified to provide maximum protection from harm, even when knee-deep in the dead.", "weight": 1610, "volume": 12, @@ -319,8 +309,7 @@ "id": "boots_larmor", "type": "ARMOR", "category": "armor", - "name": "pair of leather armor boots", - "name_plural": "pairs of leather armor boots", + "name": { "str": "pair of leather armor boots", "str_pl": "pairs of leather armor boots" }, "description": "Thick leather boots made specifically to protect the feet. Light and tough.", "weight": 902, "volume": 8, @@ -351,8 +340,7 @@ "id": "boots_lsurvivor", "type": "ARMOR", "category": "armor", - "name": "pair of light survivor boots", - "name_plural": "pairs of light survivor boots", + "name": { "str": "pair of light survivor boots", "str_pl": "pairs of light survivor boots" }, "description": "A pair of customized, Kevlar armored cloth boots, modified to provide maximum protection from harm, even when knee-deep in the dead.", "weight": 1120, "volume": 8, @@ -383,8 +371,7 @@ "id": "boots_plate", "type": "ARMOR", "category": "armor", - "name": "pair of armored boots", - "name_plural": "pairs of armored boots", + "name": { "str": "pair of armored boots", "str_pl": "pairs of armored boots" }, "description": "An extremely heavy set of armor plated boots.", "weight": 1890, "volume": 13, @@ -414,8 +401,7 @@ { "id": "boots_rubber", "type": "ARMOR", - "name": "pair of rubber boots", - "name_plural": "pairs of rubber boots", + "name": { "str": "pair of rubber boots", "str_pl": "pairs of rubber boots" }, "description": "A pair of rubber boots, often used while cleaning with caustic materials.", "weight": 980, "volume": 14, @@ -444,8 +430,7 @@ { "id": "boots_steel", "type": "ARMOR", - "name": "pair of steeltoed boots", - "name_plural": "pairs of steeltoed boots", + "name": { "str": "pair of steeltoed boots", "str_pl": "pairs of steeltoed boots" }, "description": "Leather boots with a steel toe. Extremely durable.", "weight": 1320, "volume": 12, @@ -476,8 +461,7 @@ "id": "boots_survivor", "type": "ARMOR", "category": "armor", - "name": "pair of survivor boots", - "name_plural": "pairs of survivor boots", + "name": { "str": "pair of survivor boots", "str_pl": "pairs of survivor boots" }, "description": "A pair of customized leather boots, armored with Kevlar and modified to provide maximum protection from harm, even when knee-deep in the dead.", "weight": 1330, "volume": 10, @@ -507,8 +491,7 @@ { "id": "boots_western", "type": "ARMOR", - "name": "pair of western boots", - "name_plural": "pairs of western boots", + "name": { "str": "pair of western boots", "str_pl": "pairs of western boots" }, "description": "Stiff leather boots with intricate embroidery and one-inch heels. They look good, but aren't made for running.", "weight": 1060, "volume": 10, @@ -538,8 +521,7 @@ { "id": "boots_winter", "type": "ARMOR", - "name": "pair of winter boots", - "name_plural": "pairs of winter boots", + "name": { "str": "pair of winter boots", "str_pl": "pairs of winter boots" }, "description": "Cumbersome boots designed for warmth.", "weight": 1640, "volume": 14, @@ -569,8 +551,7 @@ "id": "boots_wsurvivor", "type": "ARMOR", "category": "armor", - "name": "pair of winter survivor boots", - "name_plural": "pairs of winter survivor boots", + "name": { "str": "pair of winter survivor boots", "str_pl": "pairs of winter survivor boots" }, "description": "A pair of customized, Kevlar armored fur boots, modified to provide maximum protection from harm and the elements, even when knee-deep in the dead.", "weight": 1760, "volume": 14, @@ -601,8 +582,7 @@ "id": "boots_xlsurvivor", "type": "ARMOR", "category": "armor", - "name": "pair of XL survivor boots", - "name_plural": "pairs of XL survivor boots", + "name": { "str": "pair of XL survivor boots", "str_pl": "pairs of XL survivor boots" }, "description": "A massive pair of customized leather boots, armored with Kevlar and modified to provide maximum protection from harm and the elements, even when knee-deep in the dead.", "weight": 2460, "volume": 20, @@ -632,8 +612,7 @@ { "id": "knee_high_boots", "type": "ARMOR", - "name": "pair of knee-high boots", - "name_plural": "pairs of knee-high boots", + "name": { "str": "pair of knee-high boots", "str_pl": "pairs of knee-high boots" }, "description": "Very long leather boots that cover the lower legs. Difficult to wear but extremely durable.", "weight": 1520, "volume": 15, @@ -663,8 +642,7 @@ { "id": "roller_blades", "type": "ARMOR", - "name": "pair of rollerblades", - "name_plural": "pairs of rollerblades", + "name": { "str": "pair of rollerblades", "str_pl": "pairs of rollerblades" }, "description": "A pair of inline skates. Very fast on flat floors, but they make it hard to move on rough terrain, or to dodge effectively.", "weight": 1640, "volume": 15, @@ -693,8 +671,7 @@ { "id": "rollerskates", "type": "ARMOR", - "name": "pair of rollerskates", - "name_plural": "pairs of rollerskates", + "name": { "str": "pair of rollerskates", "str_pl": "pairs of rollerskates" }, "description": "An old-fashioned pair of leather rollerskates with steel frames. While quite fast on flat floors, they make it difficult to move on rough terrain.", "weight": 2720, "volume": 12, diff --git a/data/legacy/5/vehicle_parts.json b/data/legacy/5/vehicle_parts.json index 216e8b0ed490d..924fe9d2faf1c 100644 --- a/data/legacy/5/vehicle_parts.json +++ b/data/legacy/5/vehicle_parts.json @@ -2,8 +2,7 @@ { "type": "GENERIC", "id": "v_curtain_item", - "name": "vehicle curtain", - "name_plural": "vehicle curtains", + "name": { "str": "vehicle curtain" }, "description": "A rod, a few metal rings, and a large piece of cloth with some strings attached for securely fastening the edges.", "weight": 2200, "to_hit": -4, diff --git a/data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json b/data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json index 55bb5e2a45fd7..8dc0759196ed4 100644 --- a/data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json +++ b/data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -3,7 +3,7 @@ "type": "GENERIC", "id": "afs_biomaterial_1", "copy-from": "afs_scrap_1", - "name": { "str": "monomeric slurry" }, + "name": { "str_sp": "monomeric slurry" }, "description": "A collection of the building blocks of polymers. With this and a whole lot of know how you can create proteins and other building blocks of life.", "looks_like": "scrap" }, @@ -19,7 +19,7 @@ "type": "GENERIC", "id": "afs_biomaterial_3", "copy-from": "afs_scrap_1", - "name": { "str": "artificial muscle fibers" }, + "name": { "str_sp": "artificial muscle fibers" }, "description": "Lab grown or bioprinted muscle fibers, much denser and with higher performance ratios than baseline human muscles.", "looks_like": "scrap" }, @@ -27,7 +27,7 @@ "type": "GENERIC", "id": "afs_biomaterial_4", "copy-from": "afs_scrap_4", - "name": { "str": "self healing polymers" }, + "name": { "str_sp": "self healing polymers" }, "description": "Materials capable of taking environmental chemicals and utilizing them for self repair, be careful you don't make grey goo.", "looks_like": "scrap" }, diff --git a/data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json b/data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json index 1968618eeff09..cba9945bcabff 100644 --- a/data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json +++ b/data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json @@ -3,7 +3,7 @@ "type": "GENERIC", "id": "afs_circuitry_1", "copy-from": "afs_scrap_1", - "name": { "str": "scrap photonics" }, + "name": { "str_sp": "scrap photonics" }, "description": "Small circuits blue and gold, transmitting signals through light.", "looks_like": "scrap" }, @@ -11,7 +11,7 @@ "type": "GENERIC", "id": "afs_circuitry_2", "copy-from": "afs_scrap_2", - "name": { "str": "photonic circuitry" }, + "name": { "str": "photonic circuitry", "str_pl": "photonic circuitries" }, "description": "A resplendent golden grid inlaid on dark blue substrate.", "looks_like": "scrap" }, @@ -27,7 +27,7 @@ "type": "GENERIC", "id": "afs_circuitry_4", "copy-from": "afs_scrap_4", - "name": { "str": "hypergeometric photonics" }, + "name": { "str_sp": "hypergeometric photonics" }, "description": "In your hands lies a self-contained digital universe. Its programs glowing like stars fixed on computational shells infinitely layered.", "looks_like": "scrap" }, diff --git a/data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json b/data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json index 71e55af3b07e6..de1ef1fe91e6a 100644 --- a/data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json +++ b/data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json @@ -3,7 +3,7 @@ "type": "GENERIC", "id": "afs_energy_storage_1", "copy-from": "afs_scrap_1", - "name": { "str": "nanowire battery" }, + "name": { "str": "nanowire battery", "str_pl": "nanowire batteries" }, "description": "A small battery component with a very high energy density.", "looks_like": "scrap" }, diff --git a/data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json b/data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json index 0278bef0758af..cb2935a240929 100644 --- a/data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json +++ b/data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json @@ -35,7 +35,7 @@ "type": "GENERIC", "id": "afs_neural_io_5", "copy-from": "afs_scrap_5", - "name": { "str": "neurosynaptic interface matrix" }, + "name": { "str": "neurosynaptic interface matrix", "str_pl": "neurosynaptic interface matrices" }, "description": "A membrane of artificial neurons envelops the cerebral cortex, melding machine and human intellect into a gestalt much greater than its individual parts.", "looks_like": "scrap" } diff --git a/data/mods/Aftershock/npcs/prepnet_dialogue.json b/data/mods/Aftershock/npcs/prepnet_dialogue.json index ece38b5ffc840..d95f96b172d71 100644 --- a/data/mods/Aftershock/npcs/prepnet_dialogue.json +++ b/data/mods/Aftershock/npcs/prepnet_dialogue.json @@ -203,8 +203,8 @@ { "id": "MISSION_PrepNet_gardener_QUEST_4", "type": "mission_definition", - "name": "Faulty CBMs", - "description": "Find 5 faulty CBMs.", + "name": "Burnt Out CBMs", + "description": "Find 5 burnt out CBMs.", "goal": "MGOAL_FIND_ITEM", "difficulty": 3, "value": 0, @@ -213,7 +213,7 @@ "origins": [ "ORIGIN_SECONDARY" ], "dialogue": { "describe": "We have the ability to manufacture CBMs but lack resources.", - "offer": "If you can bring me faulty CBMs we can recycle them into new ones.", + "offer": "If you can bring me burnt out CBMs we can recycle them into new ones.", "accepted": "Thank you for accepting. You're really making yourself useful to the phyle.", "rejected": "These materials are often in dangerous areas. I understand your decision.", "advice": "Zombie scientists, technicians, shocker zombies. These are not undertaken lightly.", diff --git a/data/mods/CrazyCataclysm/crazy_comestibles.json b/data/mods/CrazyCataclysm/crazy_comestibles.json index b68acd1742247..8484f2026d12a 100644 --- a/data/mods/CrazyCataclysm/crazy_comestibles.json +++ b/data/mods/CrazyCataclysm/crazy_comestibles.json @@ -3,7 +3,7 @@ "copy-from": "cookies", "type": "COMESTIBLE", "id": "sporeos", - "name": "SpOreos", + "name": { "str_sp": "SpOreos" }, "color": "dark_gray", "spoils_in": 0, "symbol": "%", diff --git a/data/mods/Dark-Skies-Above/items/electronics.json b/data/mods/Dark-Skies-Above/items/electronics.json index ec07c8ac5ca45..baffaf3a265eb 100644 --- a/data/mods/Dark-Skies-Above/items/electronics.json +++ b/data/mods/Dark-Skies-Above/items/electronics.json @@ -4,7 +4,7 @@ "id": "broken_dks_emissary", "symbol": ",", "color": "green", - "name": "broken emissary", + "name": { "str": "broken emissary", "str_pl": "broken emissaries" }, "category": "other", "description": "The massive body of a collapsed emissary. Still a bit intimidating, perhaps knowing the damage it can cause. Could be gutted for parts.", "price": 1000, @@ -18,7 +18,7 @@ "id": "broken_dks_emissary_war", "symbol": ",", "color": "green", - "name": "broken emissary of war", + "name": { "str": "broken emissary of war", "str_pl": "broken emissaries of war" }, "category": "other", "description": "The massive body of a collapsed emissary of war. Still a bit intimidating, perhaps knowing the damage it can cause. Could be gutted for parts.", "price": 1000, @@ -32,7 +32,7 @@ "id": "broken_dks_emissary_flame", "symbol": ",", "color": "green", - "name": "broken emissary of flame", + "name": { "str": "broken emissary of flame", "str_pl": "broken emissaries of flame" }, "category": "other", "description": "The massive body of a collapsed emissary of flame. Still a bit intimidating, perhaps knowing the damage it can cause. Could be gutted for parts.", "price": 1000, diff --git a/data/mods/Dark-Skies-Above/monsters/wild_aliens/strays.json b/data/mods/Dark-Skies-Above/monsters/wild_aliens/strays.json index 31ef0afa0d4ac..4d0ec46ab741e 100644 --- a/data/mods/Dark-Skies-Above/monsters/wild_aliens/strays.json +++ b/data/mods/Dark-Skies-Above/monsters/wild_aliens/strays.json @@ -513,7 +513,7 @@ { "id": "dks_mon_stray_wretch", "type": "MONSTER", - "name": { "str": "stray wretch" }, + "name": { "str": "stray wretch", "str_pl": "stray wretches" }, "description": "This blur of jagged, crystal-fused limbs and hair might have been a housepet at some point, but now it leaps and skitters around like something out of a nightmare. It is likely that one day the very crystal that arms it will weigh overtake its body and weigh it to the ground, given its slow expansion across its body.", "default_faction": "stray", "looks_like": "mon_dog_skeleton", @@ -567,7 +567,7 @@ { "id": "dks_mon_crystal_baby", "type": "MONSTER", - "name": { "str": "germinating crystal mass" }, + "name": { "str": "germinating crystal mass", "str_pl": "germinating crystal masses" }, "description": "A human-sized mound of shimmering blue-purple crystals growing on the base of what looks like a mound of foul smelling garbage and organic leftovers. Long, thin tendrils appear to grow out of the mound, and are subtly rooting down into the ground below it, boring through dirt and concrete alike. It crackles weakly with electrical energy. If you look closely, it almost looks like something wet and meaty is squirming just inside the inner shell of crystals…", "default_faction": "stray", "bodytype": "blob", @@ -594,7 +594,7 @@ { "id": "dks_mon_crystal_shriek", "type": "MONSTER", - "name": { "str": "resonant crystal mass" }, + "name": { "str": "resonant crystal mass", "str_pl": "resonant crystal masses" }, "description": "A set of rail thin crystals growing haphazardly from a mound of rock and composted organic matter, fastened in place by thick strands of bizzare alien material. The buzzing of natural energy playing among the tines seems culminate into an almost musical sound. While pleasant at a distance, this can devolve to a deafening high pitched whine when it feels threatened.", "default_faction": "stray", "bodytype": "blob", @@ -623,7 +623,7 @@ { "id": "dks_mon_crystal_whip", "type": "MONSTER", - "name": { "str": "flailing crystal mass" }, + "name": { "str": "flailing crystal mass", "str_pl": "flailing crystal masses" }, "description": "A tall, singular crystal, growing out of a sizable pile of debris that has sprouted a multitude of thin, whiplike tendrils that constantly snake around it like feelers. It frequently grabs nearby objects and drags them into the pile beneath it, as if hoarding.", "default_faction": "stray", "bodytype": "blob", @@ -655,7 +655,7 @@ { "id": "dks_mon_crystal_zap", "type": "MONSTER", - "name": { "str": "energized crystal mass" }, + "name": { "str": "energized crystal mass", "str_pl": "energized crystal masses" }, "description": "A crooked, fiercely glowing blue-purple crystal that visibly discharges electricity into the surrounding environment without any particular intent.", "default_faction": "stray", "bodytype": "blob", diff --git a/data/mods/EW_Pack/ew_ammo.json b/data/mods/EW_Pack/ew_ammo.json index b77637f58551b..4dcc20d985fc7 100644 --- a/data/mods/EW_Pack/ew_ammo.json +++ b/data/mods/EW_Pack/ew_ammo.json @@ -3,8 +3,7 @@ "type": "AMMO", "id": "654", "price": 3800, - "name": "6.54x42mm 9N8", - "name_plural": "6.54x42mm 9N8", + "name": { "str_sp": "6.54x42mm 9N8" }, "symbol": "=", "color": "dark_gray", "description": "A 6.54x42mm cartridge, loaded with a 120 gr. FMJBT bullet. Inspired by the improved .280 British, Alexander Sarafanov himself developed the 6.54x42mm rifle cartridge for his new SVS-24 Assault Rifle.", @@ -27,8 +26,7 @@ "id": "654t", "copy-from": "654", "price": 6800, - "name": "6.54x42mm 9N12", - "name_plural": "6.54x42mm 9N12", + "name": { "str_sp": "6.54x42mm 9N12" }, "description": "The 6.54x42mm 9N12 has superior armor piercing capabilities thanks to its tungsten carbide core. Tungsten carbide was used in anti-tank rounds of the 20th and 21st century, whenever depleted uranium was unavailable or undesirable.", "material": [ "steel", "powder" ], "weight": "12 g", @@ -53,8 +51,7 @@ "type": "AMMO", "id": "20_dread", "price": 300, - "name": ".20 DREAD Pellet", - "name_plural": ".20 DREAD Pellets", + "name": { "str": ".20 DREAD Pellet" }, "symbol": "=", "color": "light_gray", "description": "These metal pellets are propelled with the help of electromagnets, therefore they do not produce sound, flash or heat signature.", diff --git a/data/mods/EW_Pack/ew_ammo_handloaded.json b/data/mods/EW_Pack/ew_ammo_handloaded.json index 40c69c7037a30..ba27a452a1efd 100644 --- a/data/mods/EW_Pack/ew_ammo_handloaded.json +++ b/data/mods/EW_Pack/ew_ammo_handloaded.json @@ -3,8 +3,7 @@ "type": "AMMO", "id": "reloaded_654", "copy-from": "654", - "name": "reloaded 6.54x42mm", - "name_plural": "reloaded 6.54x42mm", + "name": { "str_sp": "reloaded 6.54x42mm" }, "description": "Inspired by the improved .280, Alexander Sarafanov himself developed the 6.54x42mm rifle cartridge for his new SVS-24 Assault Rifle. This one has been hand-reloaded.", "relative": { "price": -400, "damage": -4, "pierce": -1, "dispersion": 85 } } diff --git a/data/mods/EW_Pack/ew_weapons.json b/data/mods/EW_Pack/ew_weapons.json index 152692c6f1937..bab3e2ba363f2 100644 --- a/data/mods/EW_Pack/ew_weapons.json +++ b/data/mods/EW_Pack/ew_weapons.json @@ -5,8 +5,7 @@ "reload_noise_volume": 10, "symbol": "(", "color": "dark_gray", - "name": "SVS-24", - "name_plural": "SVS-24", + "name": { "str_sp": "SVS-24" }, "description": "The Sarafanov Assault Rifle replaced the famous AK family of guns as the service rifle of the Russian Army. It uses the 6.54x42mm cartridge.", "price": 450000, "material": [ "steel", "plastic" ], @@ -45,8 +44,7 @@ "id": "svs-24c", "copy-from": "svs-24", "type": "GUN", - "name": "SVS-24C", - "name_plural": "SVS-24C", + "name": { "str_sp": "SVS-24C" }, "description": "The compact version of the standard SVS-24. It is commonly issued to tank crews or special forces due to its smaller size. The shorter barrel reduces accuracy.", "price": 440000, "weight": "3 kg", @@ -73,8 +71,7 @@ "copy-from": "rifle_semi", "type": "GUN", "color": "dark_gray", - "name": "CW-24", - "name_plural": "CW-24", + "name": { "str_sp": "CW-24" }, "description": "Civilian version of the SVS-24. It was made by Clearwater Arms, Georgia, for the US market. It's pure semi-automatic, and fires the weaker 5.45x39mm cartridge.", "price": 210000, "//": "Civvie version is cheaper.", @@ -113,8 +110,7 @@ "copy-from": "cw-24", "type": "GUN", "color": "light_gray", - "name": "CW-24M", - "name_plural": "CW-24M", + "name": { "str_sp": "CW-24M" }, "description": "Civilian version of the SVS-24. This one fires the same 6.54x42mm cartridge as the SVS-24.", "price": 200000, "ammo": "654" @@ -124,8 +120,7 @@ "copy-from": "cw-24", "type": "GUN", "color": "light_gray", - "name": "CW-24K", - "name_plural": "CW-24K", + "name": { "str_sp": "CW-24K" }, "description": "Civilian version of the SVS-24. This one fires the cheaper, but still powerful, 7.62x39mm cartridge.", "price": 160000, "ammo": "762", @@ -139,8 +134,7 @@ "id": "cw-24hack", "copy-from": "cw-24", "type": "GUN", - "name": "Modified CW-24", - "name_plural": "Modified CW-24", + "name": { "str_sp": "Modified CW-24" }, "description": "Civilian version of the SVS-24. It has a modified receiver and a new crudely crafted full-auto bolt carrier. Don't expect the original reliability.", "price": 420000, "dispersion": 120, @@ -151,8 +145,7 @@ "id": "cw-24m_hack", "copy-from": "cw-24m", "type": "GUN", - "name": "Modified CW-24M", - "name_plural": "Modified CW-24M", + "name": { "str_sp": "Modified CW-24M" }, "description": "Civilian version of the SVS-24. It has a modified receiver and a new crudely crafted full-auto bolt carrier. Don't expect the original reliability.", "price": 420000, "dispersion": 120, @@ -164,8 +157,7 @@ "copy-from": "rifle_semi", "type": "GUN", "color": "brown", - "name": "CWD-63", - "name_plural": "CWD-63", + "name": { "str_sp": "CWD-63" }, "description": "The Clearwater Arms version of the famous SVD-63 Dragunov. This one was rechambered for the .308 round.", "price": 170000, "material": [ "steel", "wood" ], @@ -199,8 +191,7 @@ "reload_noise_volume": 10, "symbol": "(", "color": "dark_gray", - "name": "Wrist DREAD", - "name_plural": "Wrist DREAD", + "name": { "str_sp": "Wrist DREAD" }, "description": "The miniaturized version of the DREAD MkIX attached to the wrist of the operator. It fires .20 metal pellets at an incredible rate without any flash or noise. It is mainly a defensive weapon.", "price": 160000, "material": [ "steel", "plastic" ], diff --git a/data/mods/FictonalWeapons/fic_weapons.json b/data/mods/FictonalWeapons/fic_weapons.json index b118ba98559c0..5f42684a2baa8 100644 --- a/data/mods/FictonalWeapons/fic_weapons.json +++ b/data/mods/FictonalWeapons/fic_weapons.json @@ -26,8 +26,7 @@ "copy-from": "pistol_revolver", "type": "GUN", "color": "dark_gray", - "name": "Boomlighter 454", - "name_plural": "Boomlighter 454s", + "name": { "str": "Boomlighter 454" }, "description": "Handmade by master gunsmiths at D&B Minneapolis, this deadly accurate and powerful pistol packs a punch with precision, power and flair. Comes with a one of a kind integrated flamethrower.", "price": 250000, "material": [ "steel", "plastic" ], @@ -63,8 +62,7 @@ "reload_noise_volume": 10, "symbol": "I", "color": "light_gray", - "name": "gunsword", - "name_plural": "gunswords", + "name": { "str": "gunsword" }, "description": "A long sharp blade, with two powerful .500 S&W Magnum chambers in the hilt. While chambering big rounds, the barrels are so short it slightly reduces outgoing damage.", "price": 150000, "material": [ "steel", "plastic" ], @@ -90,8 +88,7 @@ "reload_noise_volume": 10, "symbol": "i", "color": "light_gray", - "name": "gunknife", - "name_plural": "gunknives", + "name": { "str": "gunknife", "str_pl": "gunknives" }, "description": "A short but sharp blade, with two powerful .500 S&W Magnum chambers in the grip. While chambering big rounds, the barrels are so short it slightly reduces outgoing damage.", "price": 70000, "material": [ "steel", "plastic" ], @@ -119,8 +116,7 @@ "reload_noise_volume": 10, "symbol": "[", "color": "dark_gray", - "name": "FiveO handcannon", - "name_plural": "FiveO handcannons", + "name": { "str": "FiveO handcannon" }, "description": "Someone crazy thought that the .50 BMG belonged in a pistol. This massive piece of steel proves otherwise. The sheer bulk however does make it quite adept at smashing face.", "price": 60000, "material": [ "steel", "plastic" ], @@ -180,8 +176,7 @@ "id": "e1776", "copy-from": "smg_base", "type": "GUN", - "name": "Eagle 1776", - "name_plural": "Eagle 1776", + "name": { "str_sp": "Eagle 1776" }, "description": "You see before you a marvel of American engineering: a powerful .44 Magnum submachine gun, made from fine parts assembled in America, including an integral grenade launcher. Eagle 1776: From the arsenal of freedom!", "price": 580000, "material": [ "steel", "plastic" ], @@ -220,8 +215,7 @@ "reload_noise_volume": 10, "symbol": "(", "color": "dark_gray", - "name": "L.T. carbine", - "name_plural": "L.T. carbines", + "name": { "str": "L.T. carbine" }, "description": "The Lightning Trail carbine was developed for the riot police to quickly blanket an area with lightning clouds. While damaging, it is less lethal than live ammunition.", "price": 250000, "material": [ "steel", "plastic" ], @@ -254,8 +248,7 @@ "reload_noise_volume": 10, "symbol": "(", "color": "dark_gray", - "name": "arc cannon", - "name_plural": "arc cannons", + "name": { "str": "arc cannon" }, "description": "The arc cannon fires bolts of lightning arcing between targets in close proximity to each other. Originally manufactured to fry insects, now it’s been turned up to fry zombies.", "price": 250000, "material": [ "steel", "plastic" ], diff --git a/data/mods/Growable_pots/items.json b/data/mods/Growable_pots/items.json index 109ac18afd748..378bacf52e205 100644 --- a/data/mods/Growable_pots/items.json +++ b/data/mods/Growable_pots/items.json @@ -41,8 +41,7 @@ { "type": "GENERIC", "id": "gp_tomato", - "name": "garden pot (growing tomato)", - "name_plural": "garden pots (growing tomatoes)", + "name": { "str": "garden pot (growing tomato)", "str_pl": "garden pots (growing tomatoes)" }, "description": "This is a garden pot growing tomatoes. Once ripe, it can be activated to prepare them for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -57,16 +56,14 @@ { "type": "GENERIC", "id": "gp_tomato_ready", - "name": "garden pot (ripe tomato)", - "name_plural": "garden pots (ripe tomatoes)", + "name": { "str": "garden pot (ripe tomato)", "str_pl": "garden pots (ripe tomatoes)" }, "description": "This is a garden pot with a ripe tomato plant. Disassemble to retrieve the tasty 'matos.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_wheat", - "name": "garden pot (growing wheat)", - "name_plural": "garden pots (growing wheat)", + "name": { "str": "garden pot (growing wheat)", "str_pl": "garden pots (growing wheat)" }, "description": "This is a garden pot growing wheat. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -81,16 +78,14 @@ { "type": "GENERIC", "id": "gp_wheat_ready", - "name": "garden pot (ripe wheat)", - "name_plural": "garden pots (ripe wheat)", + "name": { "str": "garden pot (ripe wheat)", "str_pl": "garden pots (ripe wheat)" }, "description": "This is a garden pot with wheat ready to harvest. Disassemble to retrieve it.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_hops", - "name": "garden pot (growing hops)", - "name_plural": "garden pots (growing hops)", + "name": { "str": "garden pot (growing hops)", "str_pl": "garden pots (growing hops)" }, "description": "This is a garden pot growing hops. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -105,16 +100,14 @@ { "type": "GENERIC", "id": "gp_hops_ready", - "name": "garden pot (ripe hops)", - "name_plural": "garden pots (ripe hops)", + "name": { "str": "garden pot (ripe hops)", "str_pl": "garden pots (ripe hops)" }, "description": "This is a garden pot containing blooming hops flowers. Disassemble to harvest them.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_buckwheat", - "name": "garden pot (growing buckwheat)", - "name_plural": "garden pots (growing buckwheat)", + "name": { "str": "garden pot (growing buckwheat)", "str_pl": "garden pots (growing buckwheat)" }, "description": "This is a garden pot growing buckwheat. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -129,16 +122,14 @@ { "type": "GENERIC", "id": "gp_buckwheat_ready", - "name": "garden pot (ripe buckwheat)", - "name_plural": "garden pots (ripe buckwheat)", + "name": { "str": "garden pot (ripe buckwheat)", "str_pl": "garden pots (ripe buckwheat)" }, "description": "This is a garden pot containing ripe buckwheat stalks. Disassemble to harvest them.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_broccoli", - "name": "garden pot (growing broccoli)", - "name_plural": "garden pots (growing broccoli)", + "name": { "str": "garden pot (growing broccoli)", "str_pl": "garden pots (growing broccoli)" }, "description": "This is a garden pot growing broccoli. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -153,16 +144,14 @@ { "type": "GENERIC", "id": "gp_broccoli_ready", - "name": "garden pot (ripe broccoli)", - "name_plural": "garden pots (ripe broccoli)", + "name": { "str": "garden pot (ripe broccoli)", "str_pl": "garden pots (ripe broccoli)" }, "description": "This is a garden pot containing some fully-grown broccoli. Disassemble to harvest it.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_oats", - "name": "garden pot (growing oats)", - "name_plural": "garden pots (growing oats)", + "name": { "str": "garden pot (growing oats)", "str_pl": "garden pots (growing oats)" }, "description": "This is a garden pot growing oats. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -177,16 +166,14 @@ { "type": "GENERIC", "id": "gp_oats_ready", - "name": "garden pot (ripe oats)", - "name_plural": "garden pots (ripe oats)", + "name": { "str": "garden pot (ripe oats)", "str_pl": "garden pots (ripe oats)" }, "description": "This is a garden pot containing some golden, fully-grown oats. Disassemble to harvest them.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_barley", - "name": "garden pot (growing barley)", - "name_plural": "garden pots (growing barley)", + "name": { "str": "garden pot (growing barley)", "str_pl": "garden pots (growing barley)" }, "description": "This is a garden pot growing barley. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -201,16 +188,14 @@ { "type": "GENERIC", "id": "gp_barley_ready", - "name": "garden pot (ripe barley)", - "name_plural": "garden pots (ripe barley)", + "name": { "str": "garden pot (ripe barley)", "str_pl": "garden pots (ripe barley)" }, "description": "This is a garden pot containing some ready-to-harvest barley. Disassemble to harvest it.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_carrot", - "name": "garden pot (growing carrot)", - "name_plural": "garden pots (growing carrots)", + "name": { "str": "garden pot (growing carrot)", "str_pl": "garden pots (growing carrots)" }, "description": "This is a garden pot growing carrots. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -225,16 +210,14 @@ { "type": "GENERIC", "id": "gp_carrot_ready", - "name": "garden pot (ripe carrot)", - "name_plural": "garden pots (ripe carrot)", + "name": { "str": "garden pot (ripe carrot)", "str_pl": "garden pots (ripe carrot)" }, "description": "This is a garden pot containing some ripe carrots. Disassemble to harvest them. Store away from rabbits.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_cotton_boll", - "name": "garden pot (growing cotton)", - "name_plural": "garden pots (growing cotton)", + "name": { "str": "garden pot (growing cotton)", "str_pl": "garden pots (growing cotton)" }, "description": "This is a garden pot growing cotton. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -249,16 +232,14 @@ { "type": "GENERIC", "id": "gp_cotton_boll_ready", - "name": "garden pot (ripe cotton)", - "name_plural": "garden pots (ripe cotton)", + "name": { "str": "garden pot (ripe cotton)", "str_pl": "garden pots (ripe cotton)" }, "description": "This is a garden pot containing white, fluffy cotton bolls ready for the loom. Disassemble to pluck them.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_cabbage", - "name": "garden pot (growing cabbage)", - "name_plural": "garden pots (growing cabbage)", + "name": { "str": "garden pot (growing cabbage)", "str_pl": "garden pots (growing cabbage)" }, "description": "This is a garden pot growing cabbage. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -273,16 +254,14 @@ { "type": "GENERIC", "id": "gp_cabbage_ready", - "name": "garden pot (ripe cabbage)", - "name_plural": "garden pots (ripe cabbage)", + "name": { "str": "garden pot (ripe cabbage)", "str_pl": "garden pots (ripe cabbage)" }, "description": "This is a garden pot containing a big cabbage leaf. Disassemble to harvest it.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_cucumber", - "name": "garden pot (growing cucumber)", - "name_plural": "garden pots (growing cucumber)", + "name": { "str": "garden pot (growing cucumber)", "str_pl": "garden pots (growing cucumber)" }, "description": "This is a garden pot growing cucumber. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -297,16 +276,14 @@ { "type": "GENERIC", "id": "gp_cucumber_ready", - "name": "garden pot (ripe cucumber)", - "name_plural": "garden pots (ripe cucumber)", + "name": { "str": "garden pot (ripe cucumber)", "str_pl": "garden pots (ripe cucumber)" }, "description": "This is a garden pot containing ripe cucumbers. Disassemble to harvest them.", "copy-from": "gp_pot_grown" }, { "type": "GENERIC", "id": "gp_garlic", - "name": "garden pot (growing garlic)", - "name_plural": "garden pots (growing garlic)", + "name": { "str": "garden pot (growing garlic)", "str_pl": "garden pots (growing garlic)" }, "description": "This is a garden pot growing garlic bulbs. Once ripe, it can be activated to prepare it for harvest.", "copy-from": "gp_pot_growing", "use_action": { @@ -321,8 +298,7 @@ { "type": "GENERIC", "id": "gp_garlic_ready", - "name": "garden pot (ripe garlic)", - "name_plural": "garden pots (ripe garlic)", + "name": { "str": "garden pot (ripe garlic)", "str_pl": "garden pots (ripe garlic)" }, "description": "This is a garden pot containing pungent garlic bulbs. Disassemble to harvest them, or wave it at vampires to scare them.", "copy-from": "gp_pot_grown" } diff --git a/data/mods/Magiclysm/items/cast_spell_items.json b/data/mods/Magiclysm/items/cast_spell_items.json index e471f5d688140..33d18f1d23130 100644 --- a/data/mods/Magiclysm/items/cast_spell_items.json +++ b/data/mods/Magiclysm/items/cast_spell_items.json @@ -39,7 +39,7 @@ }, { "id": "cats_grace_potion", - "name": "Potion of Cat's Grace", + "name": { "str": "Potion of Cat's Grace", "str_pl": "Potions of Cat's Grace" }, "description": "This is a potion of Cat's Grace. It will increase your dexterity for 10 minutes.", "use_action": { "type": "cast_spell", "spell_id": "cats_grace", "no_fail": true, "level": 9 }, "type": "COMESTIBLE", @@ -60,7 +60,7 @@ }, { "id": "ogres_strength_potion", - "name": "Potion of Ogre's Strength", + "name": { "str": "Potion of Ogre's Strength", "str_pl": "Potions of Ogre's Strength" }, "description": "This is a potion of Ogre's Strength. It will increase your strength for 10 minutes.", "use_action": { "type": "cast_spell", "spell_id": "ogres_strength", "no_fail": true, "level": 9 }, "type": "COMESTIBLE", @@ -68,7 +68,7 @@ }, { "id": "eagles_sight_potion", - "name": "Potion of Eagle's Sight", + "name": { "str": "Potion of Eagle's Sight", "str_pl": "Potions of Eagle's Sight" }, "description": "This is a potion of Eagle's Sight. It will increase your perception for 10 minutes.", "use_action": { "type": "cast_spell", "spell_id": "eagles_sight", "no_fail": true, "level": 9 }, "type": "COMESTIBLE", @@ -76,7 +76,7 @@ }, { "id": "foxs_cunning_potion", - "name": "Potion of Fox's Cunning", + "name": { "str": "Potion of Fox's Cunning", "str_pl": "Potions of Fox's Cunning" }, "description": "This is a potion of Fox's Cunning. It will increase your intelligence for 10 minutes.", "use_action": { "type": "cast_spell", "spell_id": "foxs_cunning", "no_fail": true, "level": 9 }, "type": "COMESTIBLE", @@ -120,7 +120,7 @@ }, { "id": "twisted_restore_potion", - "name": "potion of Twisted Restoration", + "name": { "str": "potion of Twisted Restoration", "str_pl": "potions of Twisted Restoration" }, "description": "This foul-smelling liquid simulates undead regeneration by accelerating your heart to dangerous levels. Drinking this in danger or at critical condition may be lethal.", "use_action": { "type": "cast_spell", "spell_id": "twisted_restore", "no_fail": true, "level": 1 }, "type": "COMESTIBLE", @@ -143,7 +143,7 @@ }, { "id": "twisted_restore_potion_improved", - "name": "potion of Improved Twisted Restoration", + "name": { "str": "potion of Improved Twisted Restoration", "str_pl": "potions of Improved Twisted Restoration" }, "description": "This foul-smelling liquid simulates undead regeneration by accelerating your heart to dangerous levels. Drinking this in danger or at critical condition may be lethal. Improved infusion techniques lessen the strain of the process.", "use_action": { "type": "cast_spell", "spell_id": "twisted_restore_improved", "no_fail": true, "level": 1 }, "type": "COMESTIBLE", diff --git a/data/mods/Magiclysm/items/ethereal_items.json b/data/mods/Magiclysm/items/ethereal_items.json index d83d971db81af..cfa9ba5711987 100644 --- a/data/mods/Magiclysm/items/ethereal_items.json +++ b/data/mods/Magiclysm/items/ethereal_items.json @@ -427,7 +427,7 @@ { "id": "protect_env", "type": "ARMOR", - "name": "aura of protection", + "name": { "str": "aura of protection", "str_pl": "auras of protection" }, "description": "An all-encompassing, invisible layer of magical aura that protects you from the environment.", "weight": "1 g", "volume": "1 ml", diff --git a/data/mods/Magiclysm/items/metals.json b/data/mods/Magiclysm/items/metals.json index 6ac4fa635ba4d..90d7cc06d1edd 100644 --- a/data/mods/Magiclysm/items/metals.json +++ b/data/mods/Magiclysm/items/metals.json @@ -3,7 +3,7 @@ "id": "orichalcum_lump", "type": "AMMO", "category": "spare_parts", - "name": "lump of orichalcum", + "name": { "str": "lump of orichalcum", "str_pl": "lumps of orichalcum" }, "description": "A lump of raw orichalcum. Needs to be reformed into an ingot to be useful.", "weight": "1000 g", "volume": "250 ml", @@ -22,7 +22,7 @@ "id": "orichalcum_sliver", "type": "AMMO", "category": "spare_parts", - "name": "sliver of orichalcum", + "name": { "str": "sliver of orichalcum", "str_pl": "slivers of orichalcum" }, "description": "A sliver of orichalcum broken from a larger piece. Needs to be reformed into an ingot to be useful.", "weight": "250 g", "volume": "250 ml", @@ -57,7 +57,7 @@ "id": "mercury", "type": "AMMO", "category": "spare_parts", - "name": "liquid mercury", + "name": { "str_sp": "liquid mercury" }, "ammo_type": "mercury", "description": "Elemental liquid mercury. Known for its use in thermometers.", "volume": "1 ml", diff --git a/data/mods/Medieval_Stuff/shields.json b/data/mods/Medieval_Stuff/shields.json index 7dc288ec894be..9093c2176d1bf 100644 --- a/data/mods/Medieval_Stuff/shields.json +++ b/data/mods/Medieval_Stuff/shields.json @@ -128,8 +128,7 @@ { "id": "shield_scutum", "type": "ARMOR", - "name": "scutum", - "name_plural": "scuta", + "name": { "str": "scutum", "str_pl": "scuta" }, "category": "armor", "description": "A rectangular shield from ancient Rome, made of wood and iron. Perfect for fighting in formation, but not ideal for facing zombies alone.", "weight": "4535 g", diff --git a/data/mods/More_Survival_Tools/items.json b/data/mods/More_Survival_Tools/items.json index d6710dd2a0b28..9eb53cfae7ba5 100644 --- a/data/mods/More_Survival_Tools/items.json +++ b/data/mods/More_Survival_Tools/items.json @@ -103,8 +103,7 @@ "id": "milk_curdling", "type": "TOOL", "category": "food", - "name": "small batch of curdling milk", - "name_plural": "small batches of curdling milk", + "name": { "str": "small batch of curdling milk", "str_pl": "small batches of curdling milk" }, "description": "A sealed small waterskin filled with milk that is undergoing the process to become a crude form of cheese, having had vinegar and natural rennet added.", "weight": "1870 g", "volume": "1750 ml", @@ -129,8 +128,7 @@ "id": "milk_curdling2", "type": "TOOL", "category": "food", - "name": "batch of curdling milk", - "name_plural": "batches of curdling milk", + "name": { "str": "batch of curdling milk", "str_pl": "batches of curdling milk" }, "description": "A sealed waterskin filled with milk that is undergoing the process to become a crude form of cheese, having had vinegar and natural rennet added.", "weight": "3617 g", "volume": "3500 ml", @@ -155,8 +153,7 @@ "id": "milk_curdling3", "type": "TOOL", "category": "food", - "name": "large batch of curdling milk", - "name_plural": "large batches of curdling milk", + "name": { "str": "large batch of curdling milk", "str_pl": "large batches of curdling milk" }, "description": "A sealed large waterskin filled with milk that is undergoing the process to become a crude form of cheese, having had vinegar and natural rennet added.", "weight": "5241 g", "volume": "5250 ml", diff --git a/data/mods/Salvaged_Robots/items.json b/data/mods/Salvaged_Robots/items.json index 8f525d1da2f1d..c91a2e7bc49cf 100644 --- a/data/mods/Salvaged_Robots/items.json +++ b/data/mods/Salvaged_Robots/items.json @@ -44,8 +44,7 @@ "//": "uncontained so it can bleed to the ground.", "symbol": "~", "color": "yellow", - "name": "honey", - "name_plural": "honey", + "name": { "str_sp": "honey" }, "description": "Honey, that stuff bees make.", "price": 800, "material": "honey", diff --git a/data/mods/Salvaged_Robots/robot_additions/40mm.json b/data/mods/Salvaged_Robots/robot_additions/40mm.json index 65f252affd2d0..9fcc0cfe539c0 100644 --- a/data/mods/Salvaged_Robots/robot_additions/40mm.json +++ b/data/mods/Salvaged_Robots/robot_additions/40mm.json @@ -2,8 +2,7 @@ { "id": "40mm_emp", "type": "AMMO", - "name": "40mm EMP grenade", - "name_plural": "40mm EMP grenades", + "name": { "str": "40mm EMP grenade" }, "description": "A 40mm grenade with an EMP charge. It will release an electromagnetic pulse capable of damaging robots and some equipment.", "weight": "230 g", "volume": "250 ml", diff --git a/data/mods/Tolerate_This/comestibles.json b/data/mods/Tolerate_This/comestibles.json index 6924b8be81390..28b746046eed0 100644 --- a/data/mods/Tolerate_This/comestibles.json +++ b/data/mods/Tolerate_This/comestibles.json @@ -2,8 +2,7 @@ { "type": "COMESTIBLE", "id": "gffish_sandwich", - "name": "gluten free fish sandwich", - "name_plural": "gluten free fish sandwiches", + "name": { "str": "gluten free fish sandwich", "str_pl": "gluten free fish sandwiches" }, "weight": "222 g", "color": "yellow", "spoils_in": 24, @@ -22,8 +21,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_veggy", - "name": "gluten free vegetable sandwich", - "name_plural": "gluten free vegetable sandwiches", + "name": { "str": "gluten free vegetable sandwich", "str_pl": "gluten free vegetable sandwiches" }, "weight": "190 g", "color": "light_gray", "spoils_in": 48, @@ -64,8 +62,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_t", - "name": "gluten free meat sandwich", - "name_plural": "gluten free meat sandwiches", + "name": { "str": "gluten free meat sandwich", "str_pl": "gluten free meat sandwiches" }, "weight": "186 g", "color": "light_gray", "spoils_in": 36, @@ -83,8 +80,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_pb", - "name": "gluten free peanut butter sandwich", - "name_plural": "gluten free peanut butter sandwiches", + "name": { "str": "gluten free peanut butter sandwich", "str_pl": "gluten free peanut butter sandwiches" }, "weight": "186 g", "color": "brown", "spoils_in": 36, @@ -102,8 +98,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_pbj", - "name": "gluten free PB&J sandwich", - "name_plural": "gluten free PB&J sandwiches", + "name": { "str": "gluten free PB&J sandwich", "str_pl": "gluten free PB&J sandwiches" }, "weight": "186 g", "color": "brown", "spoils_in": 36, @@ -121,8 +116,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_pbh", - "name": "gluten free PB&H sandwich", - "name_plural": "gluten free PB&H sandwiches", + "name": { "str": "gluten free PB&H sandwich", "str_pl": "gluten free PB&H sandwiches" }, "weight": "186 g", "color": "brown", "spoils_in": 36, @@ -140,8 +134,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_pbm", - "name": "gluten free PB&M sandwich", - "name_plural": "gluten free PB&M sandwiches", + "name": { "str": "gluten free PB&M sandwich", "str_pl": "gluten free PB&M sandwiches" }, "weight": "186 g", "color": "brown", "spoils_in": 36, @@ -218,8 +211,7 @@ { "type": "COMESTIBLE", "id": "gffruit_pancakes", - "name": "gluten free fruit pancake", - "name_plural": "gluten free fruit pancakes", + "name": { "str": "gluten free fruit pancake" }, "weight": "354 g", "color": "brown", "spoils_in": 240, @@ -238,8 +230,7 @@ { "type": "COMESTIBLE", "id": "lffruit_pancakes", - "name": "lactose free fruit pancake", - "name_plural": "lactose free fruit pancakes", + "name": { "str": "lactose free fruit pancake" }, "weight": "354 g", "color": "brown", "spoils_in": 240, @@ -258,8 +249,7 @@ { "type": "COMESTIBLE", "id": "gflffruit_pancakes", - "name": "gluten free lactose free fruit pancake", - "name_plural": "gluten free lactose free fruit pancakes", + "name": { "str": "gluten free lactose free fruit pancake" }, "weight": "354 g", "color": "brown", "spoils_in": 240, @@ -278,8 +268,7 @@ { "type": "COMESTIBLE", "id": "gfchoc_pancakes", - "name": "gluten free chocolate pancake", - "name_plural": "gluten free chocolate pancakes", + "name": { "str": "gluten free chocolate pancake" }, "weight": "354 g", "color": "brown", "spoils_in": 240, @@ -297,8 +286,7 @@ { "type": "COMESTIBLE", "id": "gffrenchtoast", - "name": "gluten free French toast", - "name_plural": "gluten free French toasts", + "name": { "str": "gluten free French toast" }, "weight": "246 g", "color": "brown", "spoils_in": 240, @@ -317,8 +305,7 @@ { "type": "COMESTIBLE", "id": "gflffrenchtoast", - "name": "gluten free lactose free French toast", - "name_plural": "gluten free lactose free French toasts", + "name": { "str": "gluten free lactose free French toast" }, "weight": "246 g", "color": "brown", "spoils_in": 240, @@ -582,8 +569,7 @@ { "type": "COMESTIBLE", "id": "gfsweetbread", - "name": "gluten free sweetbread", - "name_plural": "gluten free sweetbreads", + "name": { "str": "gluten free sweetbread" }, "weight": "150 g", "color": "brown", "spoils_in": 48, @@ -603,8 +589,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_cheese", - "name": "gluten free cheese sandwich", - "name_plural": "gluten free cheese sandwiches", + "name": { "str": "gluten free cheese sandwich", "str_pl": "gluten free cheese sandwiches" }, "weight": "187 g", "color": "brown", "spoils_in": 36, @@ -622,8 +607,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_cheese_grilled", - "name": "gluten free grilled cheese sandwich", - "name_plural": "gluten free grilled cheese sandwiches", + "name": { "str": "gluten free grilled cheese sandwich", "str_pl": "gluten free grilled cheese sandwiches" }, "weight": "188 g", "color": "brown", "spoils_in": 34, @@ -643,8 +627,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_deluxe", - "name": "gluten free deluxe sandwich", - "name_plural": "gluten free deluxe sandwiches", + "name": { "str": "gluten free deluxe sandwich", "str_pl": "gluten free deluxe sandwiches" }, "weight": "340 g", "color": "brown", "spoils_in": 32, @@ -665,8 +648,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_cucumber", - "name": "gluten free cucumber sandwich", - "name_plural": "gluten free cucumber sandwiches", + "name": { "str": "gluten free cucumber sandwich", "str_pl": "gluten free cucumber sandwiches" }, "weight": "187 g", "color": "light_green", "spoils_in": 36, @@ -687,8 +669,7 @@ { "type": "COMESTIBLE", "id": "sandwich_cheese", - "name": "cheese sandwich", - "name_plural": "cheese sandwiches", + "name": { "str": "cheese sandwich", "str_pl": "cheese sandwiches" }, "weight": "187 g", "color": "brown", "spoils_in": 36, @@ -706,8 +687,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_jam", - "name": "gluten free jam sandwich", - "name_plural": "gluten free jam sandwiches", + "name": { "str": "gluten free jam sandwich", "str_pl": "gluten free jam sandwiches" }, "weight": "189 g", "color": "brown", "spoils_in": 37, @@ -725,8 +705,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_honey", - "name": "gluten free honey sandwich", - "name_plural": "gluten free honey sandwiches", + "name": { "str": "gluten free honey sandwich", "str_pl": "gluten free honey sandwiches" }, "weight": "189 g", "color": "brown", "spoils_in": 240, @@ -745,8 +724,7 @@ { "type": "COMESTIBLE", "id": "gfsandwich_sauce", - "name": "gluten free boring sandwich", - "name_plural": "gluten free boring sandwiches", + "name": { "str": "gluten free boring sandwich", "str_pl": "gluten free boring sandwiches" }, "weight": "187 g", "color": "brown", "spoils_in": 46, @@ -874,8 +852,7 @@ { "type": "COMESTIBLE", "id": "rice_milk", - "name": "rice milk", - "name_plural": "rice milk", + "name": { "str_sp": "rice milk" }, "weight": "263 g", "color": "white", "spoils_in": 24, @@ -897,8 +874,7 @@ { "type": "COMESTIBLE", "id": "coconut_water", - "name": "coconut water", - "name_plural": "coconut water", + "name": { "str_sp": "coconut water" }, "weight": "263 g", "color": "white", "spoils_in": 24, @@ -920,8 +896,7 @@ { "type": "COMESTIBLE", "id": "jar_cream_coconut", - "name": "jarred coconut milk", - "name_plural": "jarred coconut milk", + "name": { "str_sp": "jarred coconut milk" }, "weight": "258 g", "color": "white", "spoils_in": 24, @@ -940,8 +915,7 @@ { "type": "COMESTIBLE", "id": "rice_flour", - "name": "rice flour", - "name_plural": "rice flour", + "name": { "str_sp": "rice flour" }, "weight": "45 g", "color": "white", "container": "box_small", diff --git a/data/mods/blazemod/items/ammo/vortex_ammo.json b/data/mods/blazemod/items/ammo/vortex_ammo.json index 82d233959fb84..d123150aeab34 100644 --- a/data/mods/blazemod/items/ammo/vortex_ammo.json +++ b/data/mods/blazemod/items/ammo/vortex_ammo.json @@ -3,8 +3,7 @@ "id": "vpower", "type": "AMMO", "category": "chems", - "name": "vortex core", - "name_plural": "vortex core", + "name": { "str_sp": "vortex core" }, "description": "Seeing this is a bug.", "weight": 0, "volume": 0, diff --git a/data/mods/blazemod/items/fuel.json b/data/mods/blazemod/items/fuel.json index f8e49bbe59806..ac84b541900dd 100644 --- a/data/mods/blazemod/items/fuel.json +++ b/data/mods/blazemod/items/fuel.json @@ -3,8 +3,7 @@ "id": "bfeedfuel", "type": "AMMO", "category": "fuel", - "name": "liquified blob feed", - "name_plural": "bfeedfuel", + "name": { "str": "liquified blob feed", "str_pl": "bfeedfuel" }, "description": "Liquified blob feed, useful for fueling certain blob based vehicle parts", "weight": "1 g", "volume": "200ml", @@ -27,8 +26,7 @@ "id": "bfeed", "type": "AMMO", "category": "fuel", - "name": "blob feed", - "name_plural": "blob feed", + "name": { "str_sp": "blob feed" }, "description": "An amalgam of various types of organic material, contains everything the blob needs to be healthy. You think…", "weight": "50 g", "volume": "250 ml", diff --git a/data/mods/blazemod/items/tools/blob_container.json b/data/mods/blazemod/items/tools/blob_container.json index 5e529810b5e20..a0f6c32bfc300 100644 --- a/data/mods/blazemod/items/tools/blob_container.json +++ b/data/mods/blazemod/items/tools/blob_container.json @@ -2,8 +2,7 @@ { "id": "gloople_tank", "type": "CONTAINER", - "name": "gelatinous capsule", - "name_plural": "gelatinous capsules", + "name": { "str": "gelatinous capsule" }, "description": "While the blob is very eager to be fed, it's not as enthusiastic about giving up liquids. A few alterations are necessary.", "weight": "1 kg", "volume": "10 L", @@ -19,8 +18,7 @@ { "id": "gloople_tank_large", "type": "CONTAINER", - "name": "gelatinous tank", - "name_plural": "gelatinous tanks", + "name": { "str": "gelatinous tank" }, "copy-from": "gloople_tank", "weight": "6 kg", "volume": "60 L", @@ -29,8 +27,7 @@ { "id": "gray_tank", "type": "CONTAINER", - "name": "gray cocoon", - "name_plural": "gray cocoons", + "name": { "str": "gray cocoon" }, "description": "While the blob is very eager to be fed, it's not as enthusiastic about giving up liquids. A few alterations are necessary.", "weight": "3 kg", "volume": "30 L", @@ -46,8 +43,7 @@ { "id": "gray_tank_large", "type": "CONTAINER", - "name": "gray tank", - "name_plural": "gray tanks", + "name": { "str": "gray tank" }, "copy-from": "gray_tank", "weight": "10 kg", "volume": "100 L", @@ -56,8 +52,7 @@ { "id": "oozle_tank", "type": "CONTAINER", - "name": "oozing pod", - "name_plural": "oozing pods", + "name": { "str": "oozing pod" }, "description": "While the blob is very eager to be fed, it's not as enthusiastic about giving up liquids. A few alterations are necessary.", "weight": "2 kg", "volume": "20 L", @@ -73,8 +68,7 @@ { "id": "oozle_tank_large", "type": "CONTAINER", - "name": "oozing tank", - "name_plural": "oozing tanks", + "name": { "str": "oozing tank" }, "copy-from": "oozle_tank", "weight": "8 kg", "volume": "80 L", diff --git a/data/mods/blazemod/items/tools/blob_tools.json b/data/mods/blazemod/items/tools/blob_tools.json index 98a1736130b0a..9f7ad4245457e 100644 --- a/data/mods/blazemod/items/tools/blob_tools.json +++ b/data/mods/blazemod/items/tools/blob_tools.json @@ -24,8 +24,7 @@ "id": "bitergrow", "type": "TOOL", "category": "tools", - "name": "growing keratinous mass", - "name_plural": "growing keratinous mass", + "name": { "str_sp": "growing keratinous mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "4500 ml", @@ -46,8 +45,7 @@ "id": "cluttergrow", "type": "TOOL", "category": "tools", - "name": "growing beaded mass", - "name_plural": "growing beaded mass", + "name": { "str_sp": "growing beaded mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "5410 g", "volume": "2500 ml", @@ -68,8 +66,7 @@ "id": "freeziegrow", "type": "TOOL", "category": "tools", - "name": "growing icy mass", - "name_plural": "growing icy mass", + "name": { "str_sp": "growing icy mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "15140 g", "volume": "3 L", @@ -105,8 +102,7 @@ "id": "frostiegrow", "type": "TOOL", "category": "tools", - "name": "growing cold mass", - "name_plural": "growing cold mass", + "name": { "str_sp": "growing cold mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "3562 g", "volume": "2 L", @@ -127,8 +123,7 @@ "id": "fuzzlegrow", "type": "TOOL", "category": "tools", - "name": "growing hairy mass", - "name_plural": "growing hairy mass", + "name": { "str_sp": "growing hairy mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "18140 g", "volume": "5 L", @@ -149,8 +144,7 @@ "id": "gloople", "type": "TOOL", "category": "tools", - "name": "gelatinous mass", - "name_plural": "gelatinous mass", + "name": { "str_sp": "gelatinous mass" }, "description": "An experiment gone horribly right. While the original intent was to combine the structure of a bone frame with the impact absorption of the blob; the blob seems to have completely consumed the bone. Instead, what remains is an amorphous mass of goo with what seems to be numerous thin filaments floating within. With a bit of effort, you can grasp the fibers and stretch the mass into a multitude of shapes. The mass is able to retain the new shape even under force, though the mass yields at your touch. With enough strength, you think you can pull it apart.", "weight": "6662 g", "volume": "5 L", @@ -176,8 +170,7 @@ "id": "gloople_act", "type": "TOOL", "category": "tools", - "name": "multiplying gelatinous mass", - "name_plural": "multiplying gelatinous mass", + "name": { "str_sp": "multiplying gelatinous mass" }, "description": "Having been fed, this blob is now rapidly multiplying into other copies of itself; extremely noisy copies! And even worse, it's stuck to your hands until whatever it's doing is done! Catch those blobs before they bring in every zombie for miles!", "weight": "8662 g", "volume": "5 L", @@ -207,8 +200,7 @@ "id": "glooplegrow", "type": "TOOL", "category": "tools", - "name": "growing gelatinous mass", - "name_plural": "growing gelatinous mass", + "name": { "str_sp": "growing gelatinous mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "3562 g", "volume": "2 L", @@ -229,8 +221,7 @@ "id": "glowiegrow", "type": "TOOL", "category": "tools", - "name": "growing glowing mass", - "name_plural": "growing glowing mass", + "name": { "str_sp": "growing glowing mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "3562 g", "volume": "2 L", @@ -251,8 +242,7 @@ "id": "gray", "type": "TOOL", "category": "tools", - "name": "gray mass", - "name_plural": "gray mass", + "name": { "str_sp": "gray mass" }, "description": "This internal structures of this creature have developed significantly. While retaining the resilience and malleability of its once simpler form, it has gained the considerable abilities of perception and stimulus response. When directly threatened, it is able to shift and alter its microfibers, hardening its membrane to an almost steel-hard shell. You can still pull it apart with enough force. It's also really gray.", "weight": "19120 g", "volume": "15 L", @@ -278,8 +268,7 @@ "id": "gray_act", "type": "TOOL", "category": "tools", - "name": "multiplying gray mass", - "name_plural": "multiplying gray mass", + "name": { "str_sp": "multiplying gray mass" }, "description": "Having been fed, this blob is now rapidly multiplying into other copies of itself; extremely noisy copies! And even worse, it's stuck to your hands until whatever it's doing is done! Catch those blobs before they bring in every zombie for miles!", "weight": "19662 g", "volume": "5 L", @@ -309,8 +298,7 @@ "id": "graygrow", "type": "TOOL", "category": "tools", - "name": "growing gray mass", - "name_plural": "growing gray mass", + "name": { "str_sp": "growing gray mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "16335 g", "volume": "15 L", @@ -331,8 +319,7 @@ "id": "horrorgrow", "type": "TOOL", "category": "tools", - "name": "growing spike-studded mass", - "name_plural": "growing spike-studded mass", + "name": { "str_sp": "growing spike-studded mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "20140 g", "volume": "5500 ml", @@ -353,8 +340,7 @@ "id": "inkiegrow", "type": "TOOL", "category": "tools", - "name": "growing gasoline-laced mass", - "name_plural": "growing gasoline-laced mass", + "name": { "str_sp": "growing gasoline-laced mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "3 L", @@ -375,8 +361,7 @@ "id": "meltiegrow", "type": "TOOL", "category": "tools", - "name": "growing acidic mass", - "name_plural": "growing acidic mass", + "name": { "str_sp": "growing acidic mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "3 L", @@ -397,8 +382,7 @@ "id": "oozle", "type": "TOOL", "category": "tools", - "name": "oozing mass", - "name_plural": "oozing mass", + "name": { "str_sp": "oozing mass" }, "description": "An amorphous mass that has undergone a significant growth. In addition to the increased amount of goo and sinuous filaments, it seems to have started developing other internal structures. Like its smaller counterpart, it can be shaped into various structures; albeit with significantly greater tensile strength due to the increased number of supporting filaments. You believe you can split it apart with enough force.", "weight": "16262 g", "volume": "15 L", @@ -424,8 +408,7 @@ "id": "oozle_act", "type": "TOOL", "category": "tools", - "name": "multiplying oozing mass", - "name_plural": "multiplying oozing mass", + "name": { "str_sp": "multiplying oozing mass" }, "description": "Having been fed, this blob is now rapidly multiplying into other copies of itself; extremely noisy copies! And even worse, it's stuck to your hands until whatever it's doing is done! Catch those blobs before they bring in every zombie for miles!", "weight": "16662 g", "volume": "5 L", @@ -454,8 +437,7 @@ "id": "oozlegrow", "type": "TOOL", "category": "tools", - "name": "growing ooze", - "name_plural": "growing ooze", + "name": { "str_sp": "growing ooze" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12662 g", "volume": "10 L", @@ -476,8 +458,7 @@ "id": "queengrow", "type": "TOOL", "category": "tools", - "name": "growing mass of tendrils", - "name_plural": "growing mass of tendrils", + "name": { "str_sp": "growing mass of tendrils" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "25325 g", "volume": "15 L", @@ -498,8 +479,7 @@ "id": "razorqueengrow", "type": "TOOL", "category": "tools", - "name": "growing spiked mass", - "name_plural": "growing spiked mass", + "name": { "str_sp": "growing spiked mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "18140 g", "volume": "5 L", @@ -520,8 +500,7 @@ "id": "sharpgrow", "type": "TOOL", "category": "tools", - "name": "growing spiny mass", - "name_plural": "growing spiny mass", + "name": { "str_sp": "growing spiny mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "11140 g", "volume": "3500 ml", @@ -542,8 +521,7 @@ "id": "sicklegrow", "type": "TOOL", "category": "tools", - "name": "growing spiky mass", - "name_plural": "growing spiky mass", + "name": { "str_sp": "growing spiky mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "4 L", @@ -564,8 +542,7 @@ "id": "sparkiegrow", "type": "TOOL", "category": "tools", - "name": "growing bright mass", - "name_plural": "growing bright mass", + "name": { "str_sp": "growing bright mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "11140 g", "volume": "3 L", @@ -586,8 +563,7 @@ "id": "stickiegrow", "type": "TOOL", "category": "tools", - "name": "growing viscous mass", - "name_plural": "growing viscous mass", + "name": { "str_sp": "growing viscous mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "8140 g", "volume": "3 L", @@ -608,8 +584,7 @@ "id": "torchiegrow", "type": "TOOL", "category": "tools", - "name": "growing warm mass", - "name_plural": "growing warm mass", + "name": { "str_sp": "growing warm mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "3 L", @@ -630,8 +605,7 @@ "id": "voideatergrow", "type": "TOOL", "category": "tools", - "name": "growing electrified mass", - "name_plural": "growing electrified mass", + "name": { "str_sp": "growing electrified mass" }, "description": "Not quite fully grown, this blob requires nourishment to fully develop.", "weight": "12140 g", "volume": "4 L", diff --git a/data/mods/blazemod/items/tools/diamond_tools.json b/data/mods/blazemod/items/tools/diamond_tools.json index fbb2f39d013ee..1d464a2049f9b 100644 --- a/data/mods/blazemod/items/tools/diamond_tools.json +++ b/data/mods/blazemod/items/tools/diamond_tools.json @@ -25,8 +25,7 @@ { "id": "spiral_matrix", "type": "TOOL", - "name": "diamond matrix", - "name_plural": "diamond matrices", + "name": { "str": "diamond matrix", "str_pl": "diamond matrices" }, "description": "A sparkling diamond with a dazzling spiral pattern. Small pieces of glittering crystal form on the edges as you hold it.", "weight": "250 g", "volume": "250 ml", diff --git a/data/mods/blazemod/items/vehicle/blaze_other.json b/data/mods/blazemod/items/vehicle/blaze_other.json index 75963afcc8a73..4beba35b4d0ed 100644 --- a/data/mods/blazemod/items/vehicle/blaze_other.json +++ b/data/mods/blazemod/items/vehicle/blaze_other.json @@ -13,5 +13,21 @@ "material": [ "steel", "plastic" ], "symbol": "]", "color": "cyan" + }, + { + "type": "GENERIC", + "id": "vehicle_shelving", + "name": "vehicle shelving", + "description": "Several heavy frames retrofitted to be installed together which are outfitted with tie-downs and attachment points gallore for carrying an extended amount of cargo.", + "weight": "350000 g", + "to_hit": -4, + "color": "cyan", + "symbol": "]", + "material": [ "steel", "plastic" ], + "volume": "200 L", + "bashing": 2, + "category": "veh_parts", + "price": 80000, + "price_postapoc": 1000 } ] diff --git a/data/mods/blazemod/recipes/blaze_other_recipes.json b/data/mods/blazemod/recipes/blaze_other_recipes.json index 3a896d62974d4..5938ee42f8281 100644 --- a/data/mods/blazemod/recipes/blaze_other_recipes.json +++ b/data/mods/blazemod/recipes/blaze_other_recipes.json @@ -114,5 +114,24 @@ "using": [ [ "welding_standard", 6 ] ], "qualities": [ { "id": "HAMMER", "level": 2 }, { "id": "SAW_M", "level": 1 } ], "components": [ [ [ "cargo_rack", 1 ] ], [ [ "teleporter", 1 ] ], [ [ "portal", 1 ] ], [ [ "plut_cell", 5 ] ] ] + }, + { + "type": "recipe", + "result": "vehicle_shelving", + "category": "CC_OTHER", + "subcategory": "CSC_OTHER_PARTS", + "skill_used": "fabrication", + "skills_required": [ "mechanics", 4 ], + "difficulty": 4, + "time": "6 h", + "autolearn": true, + "using": [ [ "rope_natural", 4 ], [ "welding_standard", 15 ] ], + "qualities": [ + { "id": "SCREW", "level": 1 }, + { "id": "HAMMER", "level": 2 }, + { "id": "SAW_M", "level": 1 }, + { "id": "WRENCH", "level": 1 } + ], + "components": [ [ [ "cargo_rack", 4 ] ], [ [ "pipe", 16 ] ], [ [ "sheet_metal", 4 ] ], [ [ "hinge", 10 ] ] ] } ] diff --git a/data/mods/blazemod/vehicleparts/blaze_combustion.json b/data/mods/blazemod/vehicleparts/blaze_combustion.json new file mode 100644 index 0000000000000..3badc78310351 --- /dev/null +++ b/data/mods/blazemod/vehicleparts/blaze_combustion.json @@ -0,0 +1,139 @@ +[ + { + "id": "engine_steam_large", + "copy-from": "steam_engine", + "type": "vehicle_part", + "item": "steam_triple_large", + "durability": 200, + "epower": 0, + "power": 242450, + "energy_consumption": 485000, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + }, + { + "id": "engine_steam_giant", + "copy-from": "steam_engine", + "type": "vehicle_part", + "item": "steam_triple_giant", + "durability": 200, + "epower": 0, + "power": 447600, + "energy_consumption": 895250, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + }, + { + "abstract": "steam_turbine", + "copy-from": "engine_combustion", + "type": "vehicle_part", + "fuel_type": "coal_lump", + "looks_like": "diesel_engine_v12", + "m2c": 75, + "//": "45% energy efficiency", + "description": "A closed cycle, external combustion steam turbine. Burns coal from a bunker in the vehicle to produce steam.", + "extend": { "flags": [ "E_COLD_START" ] } + }, + { + "id": "engine_steam_turbine_small", + "copy-from": "steam_turbine", + "type": "vehicle_part", + "item": "steam_turbine_small", + "durability": 200, + "epower": 0, + "power": 93250, + "energy_consumption": 207250, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + }, + { + "id": "engine_steam_turbine_medium", + "copy-from": "steam_turbine", + "type": "vehicle_part", + "item": "steam_turbine_medium", + "durability": 200, + "epower": 0, + "power": 149200, + "energy_consumption": 331750, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + }, + { + "id": "engine_steam_turbine_large", + "copy-from": "steam_turbine", + "type": "vehicle_part", + "item": "steam_turbine_large", + "durability": 200, + "epower": 0, + "power": 242450, + "energy_consumption": 539000, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + }, + { + "id": "engine_steam_turbine_giant", + "copy-from": "steam_turbine", + "type": "vehicle_part", + "item": "steam_turbine_giant", + "durability": 200, + "epower": 0, + "power": 447600, + "energy_consumption": 994750, + "breaks_into": [ + { "item": "steel_lump", "count": [ 30, 60 ] }, + { "item": "steel_chunk", "count": [ 30, 60 ] }, + { "item": "scrap", "count": [ 30, 60 ] }, + { "item": "water", "count": [ 50, 120 ] } + ], + "requirements": { + "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + } + } +] diff --git a/data/mods/blazemod/vehicleparts/blaze_other_parts.json b/data/mods/blazemod/vehicleparts/blaze_other_parts.json index a2ebf9ab7c928..9581d1f17e97b 100644 --- a/data/mods/blazemod/vehicleparts/blaze_other_parts.json +++ b/data/mods/blazemod/vehicleparts/blaze_other_parts.json @@ -1,158 +1,29 @@ [ { - "id": "engine_steam_large", - "copy-from": "steam_engine", "type": "vehicle_part", - "item": "steam_triple_large", - "durability": 200, - "epower": 0, - "power": 242450, - "energy_consumption": 485000, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "id": "engine_steam_giant", - "copy-from": "steam_engine", - "type": "vehicle_part", - "item": "steam_triple_giant", - "durability": 200, - "epower": 0, - "power": 447600, - "energy_consumption": 895250, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "abstract": "steam_turbine", - "copy-from": "engine_combustion", - "type": "vehicle_part", - "fuel_type": "coal_lump", - "looks_like": "diesel_engine_v12", - "m2c": 75, - "//": "45% energy efficiency", - "description": "A closed cycle, external combustion steam turbine. Burns coal from a bunker in the vehicle to produce steam.", - "extend": { "flags": [ "E_COLD_START" ] } - }, - { - "id": "engine_steam_turbine_small", - "copy-from": "steam_turbine", - "type": "vehicle_part", - "item": "steam_turbine_small", - "durability": 200, - "epower": 0, - "power": 93250, - "energy_consumption": 207250, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "id": "engine_steam_turbine_medium", - "copy-from": "steam_turbine", - "type": "vehicle_part", - "item": "steam_turbine_medium", - "durability": 200, - "epower": 0, - "power": 149200, - "energy_consumption": 331750, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "id": "engine_steam_turbine_large", - "copy-from": "steam_turbine", - "type": "vehicle_part", - "item": "steam_turbine_large", - "durability": 200, - "epower": 0, - "power": 242450, - "energy_consumption": 539000, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "id": "engine_steam_turbine_giant", - "copy-from": "steam_turbine", - "type": "vehicle_part", - "item": "steam_turbine_giant", - "durability": 200, - "epower": 0, - "power": 447600, - "energy_consumption": 994750, - "breaks_into": [ - { "item": "steel_lump", "count": [ 30, 60 ] }, - { "item": "steel_chunk", "count": [ 30, 60 ] }, - { "item": "scrap", "count": [ 30, 60 ] }, - { "item": "water", "count": [ 50, 120 ] } - ], - "requirements": { - "install": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 3 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 6 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - } - }, - { - "abstract": "rack_blaze", - "type": "vehicle_part", - "item": "metal_tank_little", - "location": "under", - "symbol": "O", + "id": "cargo_rack_extended", + "name": "cargo shelving", + "symbol": "=", + "looks_like": "box", + "color": "light_gray", "broken_symbol": "#", - "color": "brown", - "broken_color": "blue", - "description": "This part is obsolete. It should not be installed in a vehicle, and if it is installed, you can safely uninstall it.", - "durability": 150, + "broken_color": "dark_gray", + "durability": 250, + "size": 4000, + "item": "vehicle_shelving", + "location": "center", "requirements": { - "install": { "skills": [ [ "mechanics", 1 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + "install": { "skills": [ [ "mechanics", 1 ] ], "time": "120 m", "using": [ [ "welding_standard", 5 ] ] }, + "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "120 m", "using": [ [ "welding_standard", 5 ] ] } }, - "damage_modifier": 80 + "flags": [ "OBSTACLE", "CARGO", "COVERED" ], + "breaks_into": [ + { "item": "steel_lump", "count": [ 6, 16 ] }, + { "item": "steel_chunk", "count": [ 6, 16 ] }, + { "item": "scrap", "count": [ 6, 16 ] } + ], + "damage_reduction": { "all": 28 } }, { "id": "solar_array", diff --git a/data/mods/fast_healing/meds.json b/data/mods/fast_healing/meds.json index 330f61ff7201c..62ac4f8aeba91 100644 --- a/data/mods/fast_healing/meds.json +++ b/data/mods/fast_healing/meds.json @@ -10,8 +10,7 @@ "id": "antibiotics", "type": "COMESTIBLE", "copy-from": "antibiotics", - "name": "antibiotics", - "name_plural": "antibiotics", + "name": { "str_sp": "antibiotics" }, "use_action": "STRONG_ANTIBIOTIC" } ] diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 70f88abf13af0..fb26969b55391 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1187,7 +1187,8 @@ given field for that unique event: Regardless of `stat_type`, each `event_statistic` can also have: ```C++ -"description": "Number of things" // Intended for use in describing achievement requirements. +// Intended for use in describing scores and achievement requirements. +"description": "Number of things" ``` #### `score` @@ -1199,6 +1200,9 @@ of scores. The `description` specifies a string which is expected to contain a Note that even though most statistics yield an integer, you should still use `%s`. +If the underlying statistic has a description, then the score description is +optional. It defaults to ": ". + ```C++ "id": "score_headshots", "type": "score", @@ -1228,6 +1232,26 @@ an `event_statistic`. For example: }, ``` +Currently the `"is"` field must be `">="` or `"<="` and the `"target"` must be +an integer, but these restrictions might loosen in the future. + +Another optional field is + +```C++ +"time_constraint": { "since": "game_start", "is": "<=", "target": "1 minute" } +``` + +This allows putting a time limit (either a lower or upper bound) on when the +achievement can be claimed. The `"since"` field can be either `"game_start"` +or `"cataclysm"`. The `"target"` describes an amount of time since that +reference point. + +Note that achievements can only be captured when a statistic listed in their +requirements changes. So, if you want an achievement such as "survived a +certain amount of time" which effectively only has a time constraint then you +must still place some requirement alongside it; pick some statistic which is +likely to change often, and a vacuous or weak constraint on it. + ### Skills ```C++ diff --git a/lang/extract_json_strings.py b/lang/extract_json_strings.py index e66b7b3fdb5d9..bcc596342ec83 100755 --- a/lang/extract_json_strings.py +++ b/lang/extract_json_strings.py @@ -110,7 +110,6 @@ def warning_supressed(filename): # all of their translatable strings are in the following form: # "name" member # "description" member -# "name_plural" member # "text" member # "sound" member # "messages" member containing an array of translatable strings @@ -359,19 +358,10 @@ def extract_gun(item): outfile = get_outfile("gun") if "name" in item: item_name = item.get("name") - if "name_plural" in item: - if type(item_name) is not str: - raise WrongJSONItem("ERROR: 'name_plural' found but 'name' is not a string", item) - # legacy format - if item["name_plural"] != "none": - writestr(outfile, item_name, item["name_plural"]) - else: - writestr(outfile, item_name) + if item["type"] in needs_plural: + writestr(outfile, item_name, pl_fmt=True) else: - if item["type"] in needs_plural: - writestr(outfile, item_name, new_pl_fmt=True) - else: - writestr(outfile, item_name) + writestr(outfile, item_name) if "description" in item: description = item.get("description") writestr(outfile, description) @@ -395,19 +385,10 @@ def extract_gunmod(item): outfile = get_outfile("gunmod") if "name" in item: item_name = item.get("name") - if "name_plural" in item: - if type(item_name) is not str: - raise WrongJSONItem("ERROR: 'name_plural' found but 'name' is not a string", item) - # legacy format - if item["name_plural"] != "none": - writestr(outfile, item_name, item["name_plural"]) - else: - writestr(outfile, item_name) + if item["type"] in needs_plural: + writestr(outfile, item_name, pl_fmt=True) else: - if item["type"] in needs_plural: - writestr(outfile, item_name, new_pl_fmt=True) - else: - writestr(outfile, item_name) + writestr(outfile, item_name) if "description" in item: description = item.get("description") writestr(outfile, description) @@ -879,27 +860,27 @@ def gettextify(string, context=None, plural=None): else: return "_(%r)\n" % string -def writestr(filename, string, plural=None, context=None, format_strings=False, comment=None, new_pl_fmt=False): +def writestr(filename, string, context=None, format_strings=False, comment=None, pl_fmt=False): "Wrap the string and write to the file." - if type(string) is list and plural is None: + if type(string) is list: for entry in string: - writestr(filename, entry, None, context, format_strings, comment) + writestr(filename, entry, context, format_strings, comment, pl_fmt) return - elif type(string) is dict and plural is None: + elif type(string) is dict: if "//~" in string: if comment is None: comment = string["//~"] else: comment = "{}\n{}".format(comment, string["//~"]) - ctxt = string.get( "ctxt" ) + context = string.get( "ctxt" ) str_pl = None - if new_pl_fmt: + if pl_fmt: if "str_pl" in string: str_pl = string["str_pl"] elif "str_sp" in string: str_pl = string["str_sp"] else: - # no "str_pl" entry in json, assuming regular plural form as in item_factory.cpp etc + # no "str_pl" entry in json, assuming regular plural form as in translations.cpp str_pl = "{}s".format(string["str"]) elif "str_pl" in string or "str_sp" in string: raise WrongJSONItem("ERROR: 'str_pl' and 'str_sp' not supported here", string) @@ -909,16 +890,20 @@ def writestr(filename, string, plural=None, context=None, format_strings=False, str_singular = string["str_sp"] else: raise WrongJSONItem("ERROR: 'str' or 'str_sp' not found", string) - writestr(filename, str_singular, str_pl, ctxt, format_strings, comment) - return - elif type(string) is not str and plural is not None: - raise WrongJSONItem("ERROR: 'name_plural' found but 'name' is not a string", plural) - - # don't write empty strings - if not string: return - if new_pl_fmt: - # no "str_pl" entry in json, assuming regular plural form as in item_factory.cpp etc - plural = "{}s".format(string) + elif type(string) is str: + if len(string) == 0: + # empty string has special meaning for gettext, skip it + return + str_singular = string + if pl_fmt: + # no "str_pl" entry in json, assuming regular plural form as in translations.cpp + str_pl = "{}s".format(string) + else: + str_pl = None + elif string is None: + return; + else: + raise WrongJSONItem("ERROR: value is not a string, dict, list, or None", string) with open(filename, 'a', encoding="utf-8", newline='\n') as fs: # Append developers comment @@ -926,9 +911,9 @@ def writestr(filename, string, plural=None, context=None, format_strings=False, tlcomment(fs, comment) # most of the strings from json don't use string formatting. # we must tell xgettext this explicitly - if not format_strings and "%" in string: + if not format_strings and ("%" in str_singular or (str_pl is not None and "%" in str_pl)): fs.write("# xgettext:no-python-format\n") - fs.write(gettextify(string,context=context,plural=plural)) + fs.write(gettextify(str_singular,context=context,plural=str_pl)) def get_outfile(json_object_type): return os.path.join(to_dir, json_object_type + "_from_json.py") @@ -1013,19 +998,10 @@ def extract(item, infilename): if name and name == "none": return if name: - if "name_plural" in item: - if type(name) is not str: - raise WrongJSONItem("ERROR: 'name_plural' found but 'name' is not a string", item) - # legacy format - if item["name_plural"] != "none": - writestr(outfile, name, item["name_plural"], **kwargs) - else: - writestr(outfile, name, **kwargs) + if object_type in needs_plural: + writestr(outfile, name, pl_fmt=True, **kwargs) else: - if object_type in needs_plural: - writestr(outfile, name, new_pl_fmt=True, **kwargs) - else: - writestr(outfile, name, **kwargs) + writestr(outfile, name, **kwargs) wrote = True if "name_suffix" in item: writestr(outfile, item["name_suffix"], **kwargs) @@ -1042,7 +1018,7 @@ def extract(item, infilename): if "conditional_names" in item: for cname in item["conditional_names"]: c = "Conditional name for {} when {} matches {}".format(name, cname["type"], cname["condition"]) - writestr(outfile, cname["name"], comment=c, format_strings=True, new_pl_fmt=True, **kwargs) + writestr(outfile, cname["name"], comment=c, format_strings=True, pl_fmt=True, **kwargs) wrote = True if "description" in item: if name: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e985457186654..208541b6cf9bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,13 +2,14 @@ cmake_minimum_required(VERSION 3.1.4) SET(MAIN_CPP ${CMAKE_SOURCE_DIR}/src/main.cpp) +SET(MESSAGES_CPP ${CMAKE_SOURCE_DIR}/src/messages.cpp) SET(RESOURCE_RC ${CMAKE_SOURCE_DIR}/src/resource.rc) FILE(GLOB CATACLYSM_DDA_SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp ) -LIST(REMOVE_ITEM CATACLYSM_DDA_SOURCES ${MAIN_CPP}) +LIST(REMOVE_ITEM CATACLYSM_DDA_SOURCES ${MAIN_CPP} ${MESSAGES_CPP}) FILE(GLOB CATACLYSM_DDA_HEADERS ${CMAKE_SOURCE_DIR}/src/*.h @@ -33,58 +34,60 @@ ADD_CUSTOM_COMMAND ( # Build tiles version if requested IF(TILES) - add_library(libcataclysm-tiles STATIC + add_library(cataclysm-tiles-common OBJECT ${CATACLYSM_DDA_SOURCES} ${CATACLYSM_DDA_HEADERS} ) - target_include_directories(libcataclysm-tiles INTERFACE ${CMAKE_SOURCE_DIR}/src) + target_include_directories(cataclysm-tiles-common INTERFACE ${CMAKE_SOURCE_DIR}/src) IF(WIN32) ADD_DEFINITIONS(-DUSE_WINMAIN) ADD_EXECUTABLE(cataclysm-tiles WIN32 ${MAIN_CPP} + ${MESSAGES_CPP} ${RESOURCE_RC} ) ELSE(WIN32) ADD_EXECUTABLE(cataclysm-tiles ${MAIN_CPP} + ${MESSAGES_CPP} ) ENDIF(WIN32) - ADD_DEPENDENCIES(libcataclysm-tiles get_version) + ADD_DEPENDENCIES(cataclysm-tiles-common get_version) - target_link_libraries(cataclysm-tiles libcataclysm-tiles) - target_compile_definitions(libcataclysm-tiles PUBLIC TILES ) + target_link_libraries(cataclysm-tiles cataclysm-tiles-common) + target_compile_definitions(cataclysm-tiles-common PUBLIC TILES ) IF (LOCALIZE) - target_include_directories(libcataclysm-tiles PUBLIC + target_include_directories(cataclysm-tiles-common PUBLIC ${LIBINTL_INCLUDE_DIR} ${ICONV_INCLUDE_DIR} ) - target_link_libraries(libcataclysm-tiles + target_link_libraries(cataclysm-tiles-common ${LIBINTL_LIBRARIES} ${ICONV_LIBRARIES} ) ENDIF (LOCALIZE) IF(CMAKE_USE_PTHREADS_INIT) - target_compile_options(libcataclysm-tiles PUBLIC "-pthread") + target_compile_options(cataclysm-tiles-common PUBLIC "-pthread") ENDIF(CMAKE_USE_PTHREADS_INIT) IF(CMAKE_THREAD_LIBS_INIT) - target_link_libraries(libcataclysm-tiles ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(cataclysm-tiles-common ${CMAKE_THREAD_LIBS_INIT}) ENDIF(CMAKE_THREAD_LIBS_INIT) IF (NOT DYNAMIC_LINKING) # SDL, SDL_Image, SDL_ttf deps are required for static build - target_include_directories(libcataclysm-tiles PUBLIC + target_include_directories(cataclysm-tiles-common PUBLIC ${FREETYPE_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ${BZIP2_INCLUDE_DIR} ) - target_link_libraries(libcataclysm-tiles + target_link_libraries(cataclysm-tiles-common ${FREETYPE_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} @@ -92,39 +95,39 @@ IF(TILES) ${BZIP2_LIBRARIES} ) ENDIF (NOT DYNAMIC_LINKING) - target_include_directories(libcataclysm-tiles PUBLIC + target_include_directories(cataclysm-tiles-common PUBLIC ${SDL2_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIRS} ${SDL2_TTF_INCLUDE_DIRS} ) - target_link_libraries(libcataclysm-tiles + target_link_libraries(cataclysm-tiles-common ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARIES} ${SDL2_TTF_LIBRARIES} ) IF(SOUND) - target_compile_definitions(libcataclysm-tiles PUBLIC SDL_SOUND ) - target_include_directories(libcataclysm-tiles PUBLIC ${OGGVORBIS_INCLUDE_DIR}) - target_link_libraries(libcataclysm-tiles ${OGG_LIBRARY}) - target_link_libraries(libcataclysm-tiles ${VORBIS_LIBRARY}) - target_link_libraries(libcataclysm-tiles ${VORBISFILE_LIBRARY}) - target_include_directories(libcataclysm-tiles PUBLIC ${SDL2_MIXER_INCLUDE_DIRS}) - target_link_libraries(libcataclysm-tiles ${SDL2_MIXER_LIBRARIES}) + target_compile_definitions(cataclysm-tiles-common PUBLIC SDL_SOUND ) + target_include_directories(cataclysm-tiles-common PUBLIC ${OGGVORBIS_INCLUDE_DIR}) + target_link_libraries(cataclysm-tiles-common ${OGG_LIBRARY}) + target_link_libraries(cataclysm-tiles-common ${VORBIS_LIBRARY}) + target_link_libraries(cataclysm-tiles-common ${VORBISFILE_LIBRARY}) + target_include_directories(cataclysm-tiles-common PUBLIC ${SDL2_MIXER_INCLUDE_DIRS}) + target_link_libraries(cataclysm-tiles-common ${SDL2_MIXER_LIBRARIES}) ENDIF(SOUND) IF(WIN32) # Global settings for Windows targets (at end) - target_link_libraries(libcataclysm-tiles gdi32.lib) - target_link_libraries(libcataclysm-tiles winmm.lib) - target_link_libraries(libcataclysm-tiles imm32.lib) - target_link_libraries(libcataclysm-tiles ole32.lib) - target_link_libraries(libcataclysm-tiles oleaut32.lib) - target_link_libraries(libcataclysm-tiles version.lib) + target_link_libraries(cataclysm-tiles-common gdi32.lib) + target_link_libraries(cataclysm-tiles-common winmm.lib) + target_link_libraries(cataclysm-tiles-common imm32.lib) + target_link_libraries(cataclysm-tiles-common ole32.lib) + target_link_libraries(cataclysm-tiles-common oleaut32.lib) + target_link_libraries(cataclysm-tiles-common version.lib) IF (BACKTRACE) - target_link_libraries(libcataclysm-tiles dbghelp.lib) + target_link_libraries(cataclysm-tiles-common dbghelp.lib) IF(LIBBACKTRACE) - target_link_libraries(libcataclysm-tiles backtrace) + target_link_libraries(cataclysm-tiles-common backtrace) ENDIF(LIBBACKTRACE) ENDIF(BACKTRACE) ENDIF(WIN32) @@ -136,60 +139,62 @@ ENDIF(TILES) # Build curses version if requested IF(CURSES) - add_library(libcataclysm STATIC + add_library(cataclysm-common OBJECT ${CATACLYSM_DDA_SOURCES} ${CATACLYSM_DDA_HEADERS} ) - target_include_directories(libcataclysm INTERFACE ${CMAKE_SOURCE_DIR}/src) + target_include_directories(cataclysm-common INTERFACE ${CMAKE_SOURCE_DIR}/src) IF(WIN32) ADD_EXECUTABLE(cataclysm ${MAIN_CPP} + ${MESSAGES_CPP} ${RESOURCE_RC} ) ELSE(WIN32) ADD_EXECUTABLE(cataclysm ${MAIN_CPP} + ${MESSAGES_CPP} ) ENDIF(WIN32) - ADD_DEPENDENCIES(libcataclysm get_version) - target_link_libraries(cataclysm libcataclysm) + ADD_DEPENDENCIES(cataclysm-common get_version) + target_link_libraries(cataclysm cataclysm-common) IF (LOCALIZE) - target_include_directories(libcataclysm PUBLIC + target_include_directories(cataclysm-common PUBLIC ${LIBINTL_INCLUDE_DIR} ${ICONV_INCLUDE_DIR} ) - target_link_libraries(libcataclysm + target_link_libraries(cataclysm-common ${LIBINTL_LIBRARIES} ${ICONV_LIBRARIES} ) ENDIF (LOCALIZE) - target_include_directories(libcataclysm PUBLIC ${CURSES_INCLUDE_DIR}) - target_link_libraries(libcataclysm ${CURSES_LIBRARIES}) + target_include_directories(cataclysm-common PUBLIC ${CURSES_INCLUDE_DIR}) + target_link_libraries(cataclysm-common ${CURSES_LIBRARIES}) IF(CMAKE_USE_PTHREADS_INIT) - target_compile_options(libcataclysm PUBLIC "-pthread") + target_compile_options(cataclysm-common PUBLIC "-pthread") ENDIF(CMAKE_USE_PTHREADS_INIT) IF(CMAKE_THREAD_LIBS_INIT) - target_link_libraries(libcataclysm ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(cataclysm-common ${CMAKE_THREAD_LIBS_INIT}) ENDIF(CMAKE_THREAD_LIBS_INIT) IF(WIN32) # Global settings for Windows targets (at end) - target_link_libraries(libcataclysm gdi32.lib) - target_link_libraries(libcataclysm winmm.lib) - target_link_libraries(libcataclysm imm32.lib) - target_link_libraries(libcataclysm ole32.lib) - target_link_libraries(libcataclysm oleaut32.lib) - target_link_libraries(libcataclysm version.lib) + target_link_libraries(cataclysm-common gdi32.lib) + target_link_libraries(cataclysm-common winmm.lib) + target_link_libraries(cataclysm-common imm32.lib) + target_link_libraries(cataclysm-common ole32.lib) + target_link_libraries(cataclysm-common oleaut32.lib) + target_link_libraries(cataclysm-common version.lib) IF (BACKTRACE) - target_link_libraries(libcataclysm dbghelp.lib) + target_link_libraries(cataclysm-common dbghelp.lib) IF(LIBBACKTRACE) - target_link_libraries(libcataclysm backtrace) + target_link_libraries(cataclysm-common backtrace) ENDIF(LIBBACKTRACE) ENDIF(BACKTRACE) ENDIF(WIN32) diff --git a/src/achievement.cpp b/src/achievement.cpp index e2a12ccc22ca9..452743d9bc93f 100644 --- a/src/achievement.cpp +++ b/src/achievement.cpp @@ -1,6 +1,7 @@ #include "achievement.h" #include "avatar.h" +#include "enums.h" #include "event_statistics.h" #include "generic_factory.h" #include "stats_tracker.h" @@ -42,10 +43,12 @@ generic_factory achievement_factory( "achievement" ); } // namespace -enum class achievement_comparison { - greater_equal, - last, -}; +/** @relates string_id */ +template<> +const achievement &string_id::obj() const +{ + return achievement_factory.obj( *this ); +} namespace io { @@ -55,6 +58,7 @@ std::string enum_to_string( achievement_comparison data { switch( data ) { // *INDENT-OFF* + case achievement_comparison::less_equal: return "<="; case achievement_comparison::greater_equal: return ">="; // *INDENT-ON* case achievement_comparison::last: @@ -64,17 +68,44 @@ std::string enum_to_string( achievement_comparison data abort(); } +template<> +std::string enum_to_string( achievement::time_bound::epoch data ) +{ + switch( data ) { + // *INDENT-OFF* + case achievement::time_bound::epoch::cataclysm: return "cataclysm"; + case achievement::time_bound::epoch::game_start: return "game_start"; + // *INDENT-ON* + case achievement::time_bound::epoch::last: + break; + } + debugmsg( "Invalid epoch" ); + abort(); +} + } // namespace io -template<> -struct enum_traits { - static constexpr achievement_comparison last = achievement_comparison::last; -}; +static nc_color color_from_completion( achievement_completion comp ) +{ + switch( comp ) { + case achievement_completion::pending: + return c_yellow; + case achievement_completion::completed: + return c_light_green; + case achievement_completion::failed: + return c_light_gray; + case achievement_completion::last: + break; + } + debugmsg( "Invalid achievement_completion" ); + abort(); +} struct achievement_requirement { string_id statistic; achievement_comparison comparison; int target; + bool becomes_false; void deserialize( JsonIn &jin ) { const JsonObject &jo = jin.get_object(); @@ -85,6 +116,21 @@ struct achievement_requirement { } } + void finalize() { + switch( comparison ) { + case achievement_comparison::less_equal: + becomes_false = is_increasing( statistic->monotonicity() ); + return; + case achievement_comparison::greater_equal: + becomes_false = is_decreasing( statistic->monotonicity() ); + return; + case achievement_comparison::last: + break; + } + debugmsg( "Invalid achievement_comparison" ); + abort(); + } + void check( const string_id &id ) const { if( !statistic.is_valid() ) { debugmsg( "score %s refers to invalid statistic %s", id.str(), statistic.str() ); @@ -94,6 +140,8 @@ struct achievement_requirement { bool satisifed_by( const cata_variant &v ) const { int value = v.get(); switch( comparison ) { + case achievement_comparison::less_equal: + return value <= target; case achievement_comparison::greater_equal: return value >= target; case achievement_comparison::last: @@ -104,12 +152,126 @@ struct achievement_requirement { } }; +static time_point epoch_to_time_point( achievement::time_bound::epoch e ) +{ + switch( e ) { + case achievement::time_bound::epoch::cataclysm: + return calendar::start_of_cataclysm; + case achievement::time_bound::epoch::game_start: + return calendar::start_of_game; + case achievement::time_bound::epoch::last: + break; + } + debugmsg( "Invalid epoch" ); + abort(); +} + +void achievement::time_bound::deserialize( JsonIn &jin ) +{ + const JsonObject &jo = jin.get_object(); + if( !( jo.read( "since", epoch_ ) && + jo.read( "is", comparison_ ) && + jo.read( "target", period_ ) ) ) { + jo.throw_error( "Mandatory field missing for achievement time_constaint" ); + } +} + +time_point achievement::time_bound::target() const +{ + return epoch_to_time_point( epoch_ ) + period_; +} + +achievement_completion achievement::time_bound::completed() const +{ + time_point now = calendar::turn; + switch( comparison_ ) { + case achievement_comparison::less_equal: + if( now <= target() ) { + return achievement_completion::completed; + } else { + return achievement_completion::failed; + } + case achievement_comparison::greater_equal: + if( now >= target() ) { + return achievement_completion::completed; + } else { + return achievement_completion::pending; + } + case achievement_comparison::last: + break; + } + debugmsg( "Invalid achievement_comparison" ); + abort(); +} + +std::string achievement::time_bound::ui_text() const +{ + time_point now = calendar::turn; + achievement_completion comp = completed(); + + nc_color c = color_from_completion( comp ); + + auto translate_epoch = []( epoch e ) { + switch( e ) { + case epoch::cataclysm: + return _( "time of cataclysm" ); + case epoch::game_start: + return _( "start of game" ); + case epoch::last: + break; + } + debugmsg( "Invalid epoch" ); + abort(); + }; + + std::string message = [&]() { + switch( comp ) { + case achievement_completion::pending: + return string_format( _( "At least %s from %s (%s remaining)" ), + to_string( period_ ), translate_epoch( epoch_ ), + to_string( target() - now ) ); + case achievement_completion::completed: + switch( comparison_ ) { + case achievement_comparison::less_equal: + return string_format( _( "Within %s of %s (%s remaining)" ), + to_string( period_ ), translate_epoch( epoch_ ), + to_string( target() - now ) ); + case achievement_comparison::greater_equal: + return string_format( _( "At least %s from %s (passed)" ), + to_string( period_ ), translate_epoch( epoch_ ) ); + case achievement_comparison::last: + break; + } + debugmsg( "Invalid achievement_comparison" ); + abort(); + case achievement_completion::failed: + return string_format( _( "Within %s of %s (passed)" ), + to_string( period_ ), translate_epoch( epoch_ ) ); + case achievement_completion::last: + break; + } + debugmsg( "Invalid achievement_completion" ); + abort(); + } + (); + + return colorize( message, c ); +} void achievement::load_achievement( const JsonObject &jo, const std::string &src ) { achievement_factory.load( jo, src ); } +void achievement::finalize() +{ + for( achievement &a : const_cast&>( achievement::get_all() ) ) { + for( achievement_requirement &req : a.requirements_ ) { + req.finalize(); + } + } +} + void achievement::check_consistency() { achievement_factory.check(); @@ -128,6 +290,7 @@ void achievement::reset() void achievement::load( const JsonObject &jo, const std::string & ) { mandatory( jo, was_loaded, "description", description_ ); + optional( jo, was_loaded, "time_constraint", time_constraint_ ); mandatory( jo, was_loaded, "requirements", requirements_ ); } @@ -149,6 +312,10 @@ class requirement_watcher : stat_watcher stats.add_watcher( req.statistic, this ); } + const achievement_requirement &requirement() const { + return *requirement_; + } + void new_value( const cata_variant &new_value, stats_tracker & ) override; bool is_satisfied( stats_tracker &stats ) { @@ -184,6 +351,7 @@ std::string enum_to_string( achievement_completion data // *INDENT-OFF* case achievement_completion::pending: return "pending"; case achievement_completion::completed: return "completed"; + case achievement_completion::failed: return "failed"; // *INDENT-ON* case achievement_completion::last: break; @@ -226,41 +394,54 @@ achievement_tracker::achievement_tracker( const achievement &a, achievements_tra void achievement_tracker::set_requirement( requirement_watcher *watcher, bool is_satisfied ) { - if( !sorted_watchers_[is_satisfied].insert( watcher ).second ) { - // No change - return; + if( sorted_watchers_[is_satisfied].insert( watcher ).second ) { + // Remove from other; check for completion. + sorted_watchers_[!is_satisfied].erase( watcher ); + assert( sorted_watchers_[0].size() + sorted_watchers_[1].size() == watchers_.size() ); } - // Remove from other; check for completion. - sorted_watchers_[!is_satisfied].erase( watcher ); - assert( sorted_watchers_[0].size() + sorted_watchers_[1].size() == watchers_.size() ); + achievement_completion time_comp = achievement_->time_constraint() ? + achievement_->time_constraint()->completed() : achievement_completion::completed; - if( sorted_watchers_[false].empty() ) { + if( sorted_watchers_[false].empty() && time_comp == achievement_completion::completed ) { tracker_->report_achievement( achievement_, achievement_completion::completed ); } + + if( time_comp == achievement_completion::failed || + ( !is_satisfied && watcher->requirement().becomes_false ) ) { + tracker_->report_achievement( achievement_, achievement_completion::failed ); + } } std::string achievement_tracker::ui_text( const achievement_state *state ) const { - auto color_from_completion = []( achievement_completion comp ) { - switch( comp ) { - case achievement_completion::pending: - return c_yellow; - case achievement_completion::completed: - return c_light_green; - case achievement_completion::last: - break; - } - debugmsg( "Invalid achievement_completion" ); - abort(); - }; - + // Determine overall achievement status achievement_completion comp = state ? state->completion : achievement_completion::pending; + if( comp == achievement_completion::pending && achievement_->time_constraint() && + achievement_->time_constraint()->completed() == achievement_completion::failed ) { + comp = achievement_completion::failed; + } + + // First: the achievement description nc_color c = color_from_completion( comp ); std::string result = colorize( achievement_->description(), c ) + "\n"; + + if( comp == achievement_completion::completed ) { + std::string message = string_format( + _( "Completed %s" ), to_string( state->last_state_change ) ); + result += " " + colorize( message, c ) + "\n"; + } else { + // Next: the time constraint + if( achievement_->time_constraint() ) { + result += " " + achievement_->time_constraint()->ui_text() + "\n"; + } + } + + // Next: the requirements for( const std::unique_ptr &watcher : watchers_ ) { result += " " + watcher->ui_text() + "\n"; } + return result; } diff --git a/src/achievement.h b/src/achievement.h index 52edbd9a7ff1b..4d2d1b87074a3 100644 --- a/src/achievement.h +++ b/src/achievement.h @@ -9,6 +9,7 @@ #include #include "event_bus.h" +#include "optional.h" #include "string_id.h" #include "translations.h" @@ -18,6 +19,29 @@ class achievements_tracker; class requirement_watcher; class stats_tracker; +enum class achievement_comparison { + less_equal, + greater_equal, + last, +}; + +template<> +struct enum_traits { + static constexpr achievement_comparison last = achievement_comparison::last; +}; + +enum class achievement_completion { + pending, + completed, + failed, + last +}; + +template<> +struct enum_traits { + static constexpr achievement_completion last = achievement_completion::last; +}; + class achievement { public: @@ -26,6 +50,7 @@ class achievement void load( const JsonObject &, const std::string & ); void check() const; static void load_achievement( const JsonObject &, const std::string & ); + static void finalize(); static void check_consistency(); static const std::vector &get_all(); static void reset(); @@ -37,23 +62,42 @@ class achievement return description_; } + class time_bound + { + public: + enum class epoch { + cataclysm, + game_start, + last + }; + + void deserialize( JsonIn & ); + + time_point target() const; + achievement_completion completed() const; + std::string ui_text() const; + private: + achievement_comparison comparison_; + epoch epoch_; + time_duration period_; + }; + + const cata::optional &time_constraint() const { + return time_constraint_; + } + const std::vector &requirements() const { return requirements_; } private: translation description_; + cata::optional time_constraint_; std::vector requirements_; }; -enum class achievement_completion { - pending, - completed, - last -}; - template<> -struct enum_traits { - static constexpr achievement_completion last = achievement_completion::last; +struct enum_traits { + static constexpr achievement::time_bound::epoch last = achievement::time_bound::epoch::last; }; struct achievement_state { diff --git a/src/advanced_inv.cpp b/src/advanced_inv.cpp index fd7016c3e0719..ad92a4cfbd93c 100644 --- a/src/advanced_inv.cpp +++ b/src/advanced_inv.cpp @@ -820,7 +820,7 @@ bool advanced_inventory::move_all_items( bool nested_call ) // Check some preconditions to quickly leave the function. size_t liquid_items = 0; - for( const advanced_inv_listitem elem : spane.items ) { + for( const advanced_inv_listitem &elem : spane.items ) { for( const item *elemit : elem.items ) { if( elemit->made_of_from_type( LIQUID ) && !elemit->is_frozen_liquid() ) { liquid_items++; diff --git a/src/ballistics.cpp b/src/ballistics.cpp index 7f1ce81b2df42..d3dd62c2096a9 100644 --- a/src/ballistics.cpp +++ b/src/ballistics.cpp @@ -240,14 +240,14 @@ dealt_projectile_attack projectile_attack( const projectile &proj_arg, const tri rad += ( one_in( 2 ) ? 1 : -1 ) * std::min( ARCMIN( aim.dispersion ), DEGREES( 30 ) ); // TODO: This should also represent the miss on z axis - const int offset = std::min( range, sqrtf( aim.missed_by_tiles ) ); + const int offset = std::min( range, std::sqrt( aim.missed_by_tiles ) ); int new_range = no_overshoot ? range + rng( -offset, offset ) : rng( range - offset, proj_arg.range ); new_range = std::max( new_range, 1 ); - target.x = source.x + roll_remainder( new_range * cos( rad ) ); - target.y = source.y + roll_remainder( new_range * sin( rad ) ); + target.x = source.x + roll_remainder( new_range * std::cos( rad ) ); + target.y = source.y + roll_remainder( new_range * std::sin( rad ) ); if( target == source ) { target.x = source.x + sgn( dx ); diff --git a/src/bionics.cpp b/src/bionics.cpp index e128036f1274d..baa5397877bc0 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -451,7 +451,7 @@ bool Character::activate_bionic( int b, bool eff_only ) int humidity = get_local_humidity( weatherPoint.humidity, g->weather.weather, g->is_sheltered( g->u.pos() ) ); // thirst units = 5 mL - int water_available = lround( humidity * 3.0 / 100.0 ); + int water_available = std::lround( humidity * 3.0 / 100.0 ); if( water_available == 0 ) { bio.powered = false; add_msg_if_player( m_bad, _( "There is not enough humidity in the air for your %s to function." ), @@ -1300,7 +1300,7 @@ void Character::heat_emission( int b, int fuel_energy ) const int heat_spread = std::max( heat_prod / 10 - heat_level, 1 ); g->m.emit_field( pos(), hotness, heat_spread ); } - for( const std::pair &bp : bio.info().occupied_bodyparts ) { + for( const std::pair &bp : bio.info().occupied_bodyparts ) { add_effect( effect_heating_bionic, 2_seconds, bp.first, false, heat_prod ); } } @@ -1519,7 +1519,7 @@ void Character::process_bionic( int b ) int humidity = get_local_humidity( weatherPoint.humidity, g->weather.weather, g->is_sheltered( g->u.pos() ) ); // in thirst units = 5 mL water - int water_available = lround( humidity * 3.0 / 100.0 ); + int water_available = std::lround( humidity * 3.0 / 100.0 ); // At 50% relative humidity or more, the player will draw 10 mL // At 16% relative humidity or less, the bionic will give up if( water_available == 0 ) { @@ -2219,7 +2219,7 @@ void Character::perform_install( bionic_id bid, bionic_id upbid, int difficulty, add_bionic( bid ); if( !trait_to_rem.empty() ) { - for( const trait_id tid : trait_to_rem ) { + for( const trait_id &tid : trait_to_rem ) { if( has_trait( tid ) ) { remove_mutation( tid ); } diff --git a/src/calendar.cpp b/src/calendar.cpp index 0487a74ae3b5b..464a0fd53a3e3 100644 --- a/src/calendar.cpp +++ b/src/calendar.cpp @@ -27,6 +27,7 @@ const time_point calendar::before_time_starts = time_point::from_turn( -1 ); const time_point calendar::turn_zero = time_point::from_turn( 0 ); time_point calendar::start_of_cataclysm = calendar::turn_zero; +time_point calendar::start_of_game = calendar::turn_zero; time_point calendar::turn = calendar::turn_zero; season_type calendar::initial_season = SPRING; @@ -552,7 +553,7 @@ std::string to_string( const time_point &p ) //~ 1 is the year, 2 is the day (of the *year*), 3 is the time of the day in its usual format return string_format( _( "Year %1$d, day %2$d %3$s" ), year, day, time ); } else { - const int day = day_of_season( p ); + const int day = day_of_season( p ) + 1; //~ 1 is the year, 2 is the season name, 3 is the day (of the season), 4 is the time of the day in its usual format return string_format( _( "Year %1$d, %2$s, day %3$d %4$s" ), year, calendar::name_season( season_of_year( p ) ), day, time ); diff --git a/src/calendar.h b/src/calendar.h index 9221563618531..262a95675740d 100644 --- a/src/calendar.h +++ b/src/calendar.h @@ -105,6 +105,7 @@ float season_from_default_ratio(); std::string name_season( season_type s ); extern time_point start_of_cataclysm; +extern time_point start_of_game; extern time_point turn; extern season_type initial_season; diff --git a/src/cata_tiles.cpp b/src/cata_tiles.cpp index 1f082ade9bbdf..db94aa5718f16 100644 --- a/src/cata_tiles.cpp +++ b/src/cata_tiles.cpp @@ -347,8 +347,8 @@ void tileset_loader::copy_surface_to_texture( const SDL_Surface_Ptr &surf, const std::vector &target ) { assert( surf ); - const rect_range input_range( sprite_width, sprite_height, surf->w / sprite_width, - surf->h / sprite_height ); + const rect_range input_range( sprite_width, sprite_height, point( surf->w / sprite_width, + surf->h / sprite_height ) ); const std::shared_ptr texture_ptr = CreateTextureFromSurface( renderer, surf ); assert( texture_ptr ); @@ -462,8 +462,8 @@ void tileset_loader::load_tileset( const std::string &img_path ) const rect_range output_range( max_tile_xcount * sprite_width, max_tile_ycount * sprite_height, - divide_round_up( tile_atlas->w, info.max_texture_width ), - divide_round_up( tile_atlas->h, info.max_texture_height ) ); + point( divide_round_up( tile_atlas->w, info.max_texture_width ), divide_round_up( tile_atlas->h, + info.max_texture_height ) ) ); const int expected_tilecount = ( tile_atlas->w / sprite_width ) * ( tile_atlas->h / sprite_height ); extend_vector_by( ts.tile_values, expected_tilecount ); diff --git a/src/character.cpp b/src/character.cpp index e29a1e0be82fd..8fc17e136dc4e 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -120,6 +120,7 @@ static const efftype_id effect_deaf( "deaf" ); static const efftype_id effect_disinfected( "disinfected" ); static const efftype_id effect_downed( "downed" ); static const efftype_id effect_drunk( "drunk" ); +static const efftype_id effect_earphones( "earphones" ); static const efftype_id effect_flu( "flu" ); static const efftype_id effect_foodpoison( "foodpoison" ); static const efftype_id effect_frostbite( "frostbite" ); @@ -393,7 +394,7 @@ Character::Character() : *path_settings = pathfinding_settings{ 0, 1000, 1000, 0, true, true, true, false, true }; move_mode = CMM_WALK; - + next_expected_position = cata::nullopt; temp_cur.fill( BODYTEMP_NORM ); frostbite_timer.fill( 0 ); temp_conv.fill( BODYTEMP_NORM ); @@ -3032,7 +3033,7 @@ std::vector Character::get_overlay_ids() const } // then get mutations - for( const std::pair &mut : my_mutations ) { + for( const std::pair &mut : my_mutations ) { overlay_id = ( mut.second.powered ? "active_" : "" ) + mut.first.str(); order = get_overlay_order_of_mutation( overlay_id ); mutation_sorting.insert( std::pair( order, overlay_id ) ); @@ -3770,11 +3771,11 @@ static void apply_mut_encumbrance( std::array &vals, const trait_id &mut, const body_part_set &oversize ) { - for( const std::pair &enc : mut->encumbrance_always ) { + for( const std::pair &enc : mut->encumbrance_always ) { vals[enc.first].encumbrance += enc.second; } - for( const std::pair &enc : mut->encumbrance_covered ) { + for( const std::pair &enc : mut->encumbrance_covered ) { if( !oversize.test( enc.first ) ) { vals[enc.first].encumbrance += enc.second; } @@ -10247,3 +10248,344 @@ std::vector Character::get_hostile_creatures( int range ) const && sees( critter ); } ); } + +bool Character::knows_trap( const tripoint &pos ) const +{ + const tripoint p = g->m.getabs( pos ); + return known_traps.count( p ) > 0; +} + +void Character::add_known_trap( const tripoint &pos, const trap &t ) +{ + const tripoint p = g->m.getabs( pos ); + if( t.is_null() ) { + known_traps.erase( p ); + } else { + // TODO: known_traps should map to a trap_str_id + known_traps[p] = t.id.str(); + } +} + +bool Character::can_hear( const tripoint &source, const int volume ) const +{ + if( is_deaf() ) { + return false; + } + + // source is in-ear and at our square, we can hear it + if( source == pos() && volume == 0 ) { + return true; + } + const int dist = rl_dist( source, pos() ); + const float volume_multiplier = hearing_ability(); + return ( volume - weather::sound_attn( g->weather.weather ) ) * volume_multiplier >= dist; +} + +float Character::hearing_ability() const +{ + float volume_multiplier = 1.0; + + // Mutation/Bionic volume modifiers + if( has_active_bionic( bio_ears ) && !has_active_bionic( bio_earplugs ) ) { + volume_multiplier *= 3.5; + } + if( has_trait( trait_PER_SLIME ) ) { + // Random hearing :-/ + // (when it's working at all, see player.cpp) + // changed from 0.5 to fix Mac compiling error + volume_multiplier *= ( rng( 1, 2 ) ); + } + + volume_multiplier *= Character::mutation_value( "hearing_modifier" ); + + if( has_effect( effect_deaf ) ) { + // Scale linearly up to 30 minutes + volume_multiplier *= ( 30_minutes - get_effect_dur( effect_deaf ) ) / 30_minutes; + } + + if( has_effect( effect_earphones ) ) { + volume_multiplier *= .25; + } + + return volume_multiplier; +} + +std::vector Character::short_description_parts() const +{ + std::vector result; + + if( is_armed() ) { + result.push_back( _( "Wielding: " ) + weapon.tname() ); + } + const std::string worn_str = enumerate_as_string( worn.begin(), worn.end(), + []( const item & it ) { + return it.tname(); + } ); + if( !worn_str.empty() ) { + result.push_back( _( "Wearing: " ) + worn_str ); + } + const int visibility_cap = 0; // no cap + const auto trait_str = visible_mutations( visibility_cap ); + if( !trait_str.empty() ) { + result.push_back( _( "Traits: " ) + trait_str ); + } + return result; +} + +std::string Character::short_description() const +{ + return join( short_description_parts(), "; " ); +} + +int Character::print_info( const catacurses::window &w, int vStart, int, int column ) const +{ + mvwprintw( w, point( column, vStart++ ), _( "You (%s)" ), name ); + return vStart; +} + +void Character::shift_destination( const point &shift ) +{ + if( next_expected_position ) { + *next_expected_position += shift; + } + + for( auto &elem : auto_move_route ) { + elem += shift; + } +} + +bool Character::has_weapon() const +{ + return !unarmed_attack(); +} + +int Character::get_hp() const +{ + return get_hp( num_hp_parts ); +} + +int Character::get_hp( hp_part bp ) const +{ + if( bp < num_hp_parts ) { + return hp_cur[bp]; + } + int hp_total = 0; + for( int i = 0; i < num_hp_parts; ++i ) { + hp_total += hp_cur[i]; + } + return hp_total; +} + +int Character::get_hp_max() const +{ + return get_hp_max( num_hp_parts ); +} + +int Character::get_hp_max( hp_part bp ) const +{ + if( bp < num_hp_parts ) { + return hp_max[bp]; + } + int hp_total = 0; + for( int i = 0; i < num_hp_parts; ++i ) { + hp_total += hp_max[i]; + } + return hp_total; +} + +Creature::Attitude Character::attitude_to( const Creature &other ) const +{ + const auto m = dynamic_cast( &other ); + if( m != nullptr ) { + if( m->friendly != 0 ) { + return A_FRIENDLY; + } + switch( m->attitude( const_cast( this ) ) ) { + // player probably does not want to harm them, but doesn't care much at all. + case MATT_FOLLOW: + case MATT_FPASSIVE: + case MATT_IGNORE: + case MATT_FLEE: + return A_NEUTRAL; + // player does not want to harm those. + case MATT_FRIEND: + case MATT_ZLAVE: + // Don't want to harm your zlave! + return A_FRIENDLY; + case MATT_ATTACK: + return A_HOSTILE; + case MATT_NULL: + case NUM_MONSTER_ATTITUDES: + break; + } + + return A_NEUTRAL; + } + + const auto p = dynamic_cast( &other ); + if( p != nullptr ) { + if( p->is_enemy() ) { + return A_HOSTILE; + } else if( p->is_player_ally() ) { + return A_FRIENDLY; + } else { + return A_NEUTRAL; + } + } else if( &other == this ) { + return A_FRIENDLY; + } + + return A_NEUTRAL; +} + +bool Character::sees( const tripoint &t, bool, int ) const +{ + const int wanted_range = rl_dist( pos(), t ); + bool can_see = is_player() ? g->m.pl_sees( t, wanted_range ) : + Creature::sees( t ); + // Clairvoyance is now pretty cheap, so we can check it early + if( wanted_range < MAX_CLAIRVOYANCE && wanted_range < clairvoyance() ) { + return true; + } + // Only check if we need to override if we already came to the opposite conclusion. + if( can_see && wanted_range < 15 && wanted_range > sight_range( 1 ) && + has_active_bionic( str_bio_night ) ) { + can_see = false; + } + if( can_see && wanted_range > unimpaired_range() ) { + can_see = false; + } + + return can_see; +} + +bool Character::sees( const Creature &critter ) const +{ + // This handles only the player/npc specific stuff (monsters don't have traits or bionics). + const int dist = rl_dist( pos(), critter.pos() ); + if( dist <= 3 && has_active_mutation( trait_ANTENNAE ) ) { + return true; + } + + return Creature::sees( critter ); +} + +nc_color Character::bodytemp_color( int bp ) const +{ + nc_color color = c_light_gray; // default + if( bp == bp_eyes ) { + color = c_light_gray; // Eyes don't count towards warmth + } else if( temp_conv[bp] > BODYTEMP_SCORCHING ) { + color = c_red; + } else if( temp_conv[bp] > BODYTEMP_VERY_HOT ) { + color = c_light_red; + } else if( temp_conv[bp] > BODYTEMP_HOT ) { + color = c_yellow; + } else if( temp_conv[bp] > BODYTEMP_COLD ) { + color = c_green; + } else if( temp_conv[bp] > BODYTEMP_VERY_COLD ) { + color = c_light_blue; + } else if( temp_conv[bp] > BODYTEMP_FREEZING ) { + color = c_cyan; + } else if( temp_conv[bp] <= BODYTEMP_FREEZING ) { + color = c_blue; + } + return color; +} + +void Character::set_destination( const std::vector &route, + const player_activity &new_destination_activity ) +{ + auto_move_route = route; + set_destination_activity( new_destination_activity ); + destination_point.emplace( g->m.getabs( route.back() ) ); +} + +void Character::clear_destination() +{ + auto_move_route.clear(); + clear_destination_activity(); + destination_point = cata::nullopt; + next_expected_position = cata::nullopt; +} + +bool Character::has_distant_destination() const +{ + return has_destination() && !get_destination_activity().is_null() && + get_destination_activity().id() == "ACT_TRAVELLING" && !omt_path.empty(); +} + +bool Character::is_auto_moving() const +{ + return destination_point.has_value(); +} + +bool Character::has_destination() const +{ + return !auto_move_route.empty(); +} + +bool Character::has_destination_activity() const +{ + return !get_destination_activity().is_null() && destination_point && + position == g->m.getlocal( *destination_point ); +} + +void Character::start_destination_activity() +{ + if( !has_destination_activity() ) { + debugmsg( "Tried to start invalid destination activity" ); + return; + } + + assign_activity( get_destination_activity() ); + clear_destination(); +} + +std::vector &Character::get_auto_move_route() +{ + return auto_move_route; +} + +action_id Character::get_next_auto_move_direction() +{ + if( !has_destination() ) { + return ACTION_NULL; + } + + if( next_expected_position ) { + if( pos() != *next_expected_position ) { + // We're off course, possibly stumbling or stuck, cancel auto move + return ACTION_NULL; + } + } + + next_expected_position.emplace( auto_move_route.front() ); + auto_move_route.erase( auto_move_route.begin() ); + + tripoint dp = *next_expected_position - pos(); + + // Make sure the direction is just one step and that + // all diagonal moves have 0 z component + if( std::abs( dp.x ) > 1 || std::abs( dp.y ) > 1 || std::abs( dp.z ) > 1 || + ( std::abs( dp.z ) != 0 && ( std::abs( dp.x ) != 0 || std::abs( dp.y ) != 0 ) ) ) { + // Should never happen, but check just in case + return ACTION_NULL; + } + return get_movement_action_from_delta( dp, iso_rotate::yes ); +} + +bool Character::defer_move( const tripoint &next ) +{ + // next must be adjacent to current pos + if( square_dist( next, pos() ) != 1 ) { + return false; + } + // next must be adjacent to subsequent move in any preexisting automove route + if( has_destination() && square_dist( auto_move_route.front(), next ) != 1 ) { + return false; + } + auto_move_route.insert( auto_move_route.begin(), next ); + next_expected_position = pos(); + return true; +} diff --git a/src/character.h b/src/character.h index 0cd1de152159a..3280001daf582 100644 --- a/src/character.h +++ b/src/character.h @@ -1581,10 +1581,12 @@ class Character : public Creature, public visitable player_activity stashed_outbounds_backlog; player_activity activity; std::list backlog; + cata::optional destination_point; inventory inv; itype_id last_item; item weapon; + int scent; pimpl my_bionics; character_martial_arts martial_arts_data; @@ -1598,6 +1600,13 @@ class Character : public Creature, public visitable int slow_rad; int focus_pool; + int cash; + std::set follower_ids; + weak_ptr_fast last_target; + cata::optional last_target_pos; + // Save favorite ammo location + item_location ammo_location; + std::set camps; /* crafting inventory cached time */ time_point cached_time; @@ -2059,6 +2068,50 @@ class Character : public Creature, public visitable /** Recalculates morale penalty/bonus from wetness based on mutations, equipment and temperature */ void apply_wetness_morale( int temperature ); int heartrate_bpm() const; + std::vector short_description_parts() const; + std::string short_description() const; + int print_info( const catacurses::window &w, int vStart, int vLines, int column ) const override; + // Checks whether a player can hear a sound at a given volume and location. + bool can_hear( const tripoint &source, int volume ) const; + // Returns a multiplier indicating the keenness of a player's hearing. + float hearing_ability() const; + + using trap_map = std::map; + bool knows_trap( const tripoint &pos ) const; + void add_known_trap( const tripoint &pos, const trap &t ); + /** Define color for displaying the body temperature */ + nc_color bodytemp_color( int bp ) const; + + // see Creature::sees + bool sees( const tripoint &t, bool is_player = false, int range_mod = 0 ) const override; + // see Creature::sees + bool sees( const Creature &critter ) const override; + Attitude attitude_to( const Creature &other ) const override; + + int get_hp( hp_part bp ) const override; + int get_hp() const override; + int get_hp_max( hp_part bp ) const override; + int get_hp_max() const override; + bool has_weapon() const override; + void shift_destination( const point &shift ); + // Auto move methods + void set_destination( const std::vector &route, + const player_activity &new_destination_activity = player_activity() ); + void clear_destination(); + bool has_distant_destination() const; + + // true if the player is auto moving, or if the player is going to finish + // auto moving but the destination is not yet reset, such as in avatar_action::move + bool is_auto_moving() const; + // true if there are further moves in the auto move route + bool has_destination() const; + // true if player has destination activity AND is standing on destination tile + bool has_destination_activity() const; + // starts destination activity and cleans up to ensure it is called only once + void start_destination_activity(); + std::vector &get_auto_move_route(); + action_id get_next_auto_move_direction(); + bool defer_move( const tripoint &next ); protected: Character(); @@ -2102,9 +2155,14 @@ class Character : public Creature, public visitable // the player's activity level for metabolism calculations float activity_level = NO_EXERCISE; + trap_map known_traps; std::array encumbrance_cache; mutable std::map cached_info; - + bool bio_soporific_powered_at_last_sleep_check; + /** last time we checked for sleep */ + time_point last_sleep_check = calendar::turn_zero; + /** warnings from a faction about bad behavior */ + std::map> warning_record; /** * Traits / mutations of the character. Key is the mutation id (it's also a valid * key into @ref mutation_data), the value describes the status of the mutation. @@ -2210,6 +2268,9 @@ class Character : public Creature, public visitable int radiation; + std::vector auto_move_route; + // Used to make sure auto move is canceled if we stumble off course + cata::optional next_expected_position; scenttype_id type_of_scent; struct weighted_int_list melee_miss_reasons; diff --git a/src/consumption.cpp b/src/consumption.cpp index 70ce57930213c..6d8778a2c2d7c 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -957,7 +957,7 @@ bool player::eat( item &food, bool force ) } if( has_active_bionic( bio_taste_blocker ) ) { - mod_power_level( units::from_kilojoule( -abs( food.get_comestible_fun() ) ) ); + mod_power_level( units::from_kilojoule( -std::abs( food.get_comestible_fun() ) ) ); } if( food.has_flag( flag_FUNGAL_VECTOR ) && !has_trait( trait_M_IMMUNE ) ) { diff --git a/src/coordinates.h b/src/coordinates.h index b8f09429a6ce4..d39c62fd0e74b 100644 --- a/src/coordinates.h +++ b/src/coordinates.h @@ -75,9 +75,9 @@ struct real_coords { } // specifically for the subjective position returned by overmap::draw - void fromomap( int rel_omx, int rel_omy, int rel_om_posx, int rel_om_posy ) { - const int ax = rel_omx * OMAPX + rel_om_posx; - const int ay = rel_omy * OMAPY + rel_om_posy; + void fromomap( const point &rel_om, const point &rel_om_pos ) { + const int ax = rel_om.x * OMAPX + rel_om_pos.x; + const int ay = rel_om.y * OMAPY + rel_om_pos.y; fromabs( ax * SEEX * 2, ay * SEEY * 2 ); } diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index c5383c07e7198..8d286387e31d2 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -126,16 +126,16 @@ void reset_recipe_categories() craft_subcat_list.clear(); } -static int print_items( const recipe &r, const catacurses::window &w, int ypos, int xpos, +static int print_items( const recipe &r, const catacurses::window &w, point pos, nc_color col, int batch ) { if( !r.has_byproducts() ) { return 0; } - const int oldy = ypos; + const int oldy = pos.y; - mvwprintz( w, point( xpos, ypos++ ), col, _( "Byproducts:" ) ); + mvwprintz( w, point( pos.x, pos.y++ ), col, _( "Byproducts:" ) ); for( const auto &bp : r.byproducts ) { const auto t = item::find_type( bp.first ); int amount = bp.second * batch; @@ -147,10 +147,10 @@ static int print_items( const recipe &r, const catacurses::window &w, int ypos, desc = string_format( "> %d %s", amount, t->nname( static_cast( amount ) ) ); } - mvwprintz( w, point( xpos, ypos++ ), col, desc ); + mvwprintz( w, point( pos.x, pos.y++ ), col, desc ); } - return ypos - oldy; + return pos.y - oldy; } const recipe *select_crafting_recipe( int &batch_size ) @@ -539,7 +539,7 @@ const recipe *select_crafting_recipe( int &batch_size ) _( "Cannot be crafted because the same item is needed " "for multiple components" ) ); } - ypos += print_items( *current[line], w_data, ypos, xpos, col, batch ? line + 1 : 1 ); + ypos += print_items( *current[line], w_data, point( xpos, ypos ), col, batch ? line + 1 : 1 ); } //color needs to be preserved in case part of the previous page was cut off diff --git a/src/debug.cpp b/src/debug.cpp index ab55431f7571c..d0e9f05f7b083 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -290,7 +290,7 @@ static time_info get_time() noexcept const auto current = localtime( &tt ); return time_info { current->tm_hour, current->tm_min, current->tm_sec, - static_cast( lround( tv.tv_usec / 1000.0 ) ) + static_cast( std::lround( tv.tv_usec / 1000.0 ) ) }; } #endif diff --git a/src/debug_menu.h b/src/debug_menu.h index 25cb7c20020c9..2eb6a1caa0af0 100644 --- a/src/debug_menu.h +++ b/src/debug_menu.h @@ -21,7 +21,8 @@ void teleport_overmap(); void spawn_nested_mapgen(); void character_edit_menu(); -void wishitem( player *p = nullptr, int x = -1, int y = -1, int z = -1 ); +void wishitem( player *p = nullptr ); +void wishitem( player *p, const tripoint & ); void wishmonster( const cata::optional &p ); void wishmutate( player *p ); void wishskill( player *p ); diff --git a/src/editmap.cpp b/src/editmap.cpp index 8ebe6f75b78b7..b39643e60eceb 100644 --- a/src/editmap.cpp +++ b/src/editmap.cpp @@ -1287,7 +1287,7 @@ void editmap::edit_itm() g->draw_panels(); } while( imenu.ret != UILIST_CANCEL ); } else if( ilmenu.ret == static_cast( items.size() ) ) { - debug_menu::wishitem( nullptr, target.x, target.y, target.z ); + debug_menu::wishitem( nullptr, target ); ilmenu.entries.clear(); i = 0; for( auto &an_item : items ) { diff --git a/src/enums.h b/src/enums.h index b33114cfeaee2..b8ae393b3c3a4 100644 --- a/src/enums.h +++ b/src/enums.h @@ -282,4 +282,21 @@ struct game_message_params { game_message_flags flags; }; +enum class monotonically : int { + constant, + increasing, + decreasing, + unknown, +}; + +constexpr bool is_increasing( monotonically m ) +{ + return m == monotonically::constant || m == monotonically::increasing; +} + +constexpr bool is_decreasing( monotonically m ) +{ + return m == monotonically::constant || m == monotonically::decreasing; +} + #endif // CATA_SRC_ENUMS_H diff --git a/src/event_statistics.cpp b/src/event_statistics.cpp index 300e309d1d253..28e57c5aa25b9 100644 --- a/src/event_statistics.cpp +++ b/src/event_statistics.cpp @@ -8,6 +8,7 @@ #include "cata_variant.h" #include "debug.h" +#include "enums.h" #include "event.h" #include "event_field_transformations.h" #include "generic_factory.h" @@ -144,6 +145,7 @@ class event_transformation::impl virtual event_multiset initialize( stats_tracker & ) const = 0; virtual std::unique_ptr watch( stats_tracker & ) const = 0; virtual void check( const std::string &/*name*/ ) const {} + virtual monotonically monotonicity() const = 0; virtual std::unique_ptr clone() const = 0; }; @@ -154,6 +156,7 @@ class event_statistic::impl virtual cata_variant value( stats_tracker & ) const = 0; virtual std::unique_ptr watch( stats_tracker & ) const = 0; virtual void check( const std::string &/*name*/ ) const {} + virtual monotonically monotonicity() const = 0; virtual std::unique_ptr clone() const = 0; }; @@ -203,6 +206,11 @@ struct value_constraint { name, equals_statistic_->str() ); } } + + bool is_constant() const { + return !equals_statistic_ || + ( *equals_statistic_ )->monotonicity() == monotonically::constant; + } }; struct new_field { @@ -277,6 +285,14 @@ struct event_source { stats.add_watcher( transformation, watcher ); } } + + monotonically monotonicity() const { + if( transformation.is_empty() ) { + return monotonically::increasing; + } else { + return transformation->monotonicity(); + } + } }; struct event_transformation_impl : public event_transformation::impl { @@ -398,6 +414,15 @@ struct event_transformation_impl : public event_transformation::impl { } } + monotonically monotonicity() const override { + for( const std::pair &constraint : constraints_ ) { + if( !constraint.second.is_constant() ) { + return monotonically::unknown; + } + } + return monotonically::increasing; + } + std::unique_ptr clone() const override { return std::make_unique( *this ); } @@ -435,6 +460,11 @@ void event_transformation::check() const impl_->check( id.str() ); } +monotonically event_transformation::monotonicity() const +{ + return impl_->monotonicity(); +} + struct event_statistic_count : event_statistic::impl { event_statistic_count( const string_id &i, const event_source &s ) : id( i ), @@ -474,6 +504,10 @@ struct event_statistic_count : event_statistic::impl { return std::make_unique( this, stats ); } + monotonically monotonicity() const override { + return source.monotonicity(); + } + std::unique_ptr clone() const override { return std::make_unique( *this ); } @@ -519,6 +553,10 @@ struct event_statistic_total : event_statistic::impl { return std::make_unique( this, stats ); } + monotonically monotonicity() const override { + return source.monotonicity(); + } + std::unique_ptr clone() const override { return std::make_unique( *this ); } @@ -595,6 +633,14 @@ struct event_statistic_unique_value : event_statistic::impl { } } + monotonically monotonicity() const override { + if( type_ == event_type::game_start ) { + return monotonically::constant; + } else { + return monotonically::unknown; + } + } + std::unique_ptr clone() const override { return std::make_unique( *this ); } @@ -640,9 +686,20 @@ void event_statistic::check() const impl_->check( id.str() ); } +monotonically event_statistic::monotonicity() const +{ + return impl_->monotonicity(); +} + std::string score::description( stats_tracker &stats ) const { - return string_format( description_.translated(), value( stats ).get_string() ); + std::string value_string = value( stats ).get_string(); + if( description_.empty() ) { + //~ Default format for scores. %1$s is statistic description; %2$s is value. + return string_format( _( "%1$s: %2$s" ), this->stat_->description(), value_string ); + } else { + return string_format( description_.translated(), value_string ); + } } cata_variant score::value( stats_tracker &stats ) const @@ -652,7 +709,7 @@ cata_variant score::value( stats_tracker &stats ) const void score::load( const JsonObject &jo, const std::string & ) { - mandatory( jo, was_loaded, "description", description_ ); + optional( jo, was_loaded, "description", description_ ); mandatory( jo, was_loaded, "statistic", stat_ ); } diff --git a/src/event_statistics.h b/src/event_statistics.h index 1a93759e18816..bae47d0676f08 100644 --- a/src/event_statistics.h +++ b/src/event_statistics.h @@ -12,9 +12,9 @@ class cata_variant; class event_multiset; - enum class event_type : int; class JsonObject; +enum class monotonically : int; class stats_tracker; class stats_tracker_state; @@ -48,8 +48,9 @@ class event_transformation string_id id; bool was_loaded = false; - class impl; + monotonically monotonicity() const; + class impl; private: cata::clone_ptr impl_; }; @@ -74,8 +75,9 @@ class event_statistic return description_; } - class impl; + monotonically monotonicity() const; + class impl; private: std::string description_; cata::clone_ptr impl_; diff --git a/src/explosion.cpp b/src/explosion.cpp index 4a2ee9b1fdd28..83e539086b976 100644 --- a/src/explosion.cpp +++ b/src/explosion.cpp @@ -136,7 +136,7 @@ static float mass_to_area( const float mass ) // Density of steel in g/cm^3 constexpr float steel_density = 7.85; float fragment_volume = ( mass / 1000.0 ) / steel_density; - float fragment_radius = cbrt( ( fragment_volume * 3.0 ) / ( 4.0 * M_PI ) ); + float fragment_radius = std::cbrt( ( fragment_volume * 3.0 ) / ( 4.0 * M_PI ) ); return fragment_radius * fragment_radius * M_PI; } diff --git a/src/faction.cpp b/src/faction.cpp index 9a64be917041e..f5fc288adbb5c 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -547,13 +547,9 @@ int npc::faction_display( const catacurses::window &fac_w, const int width ) con nc_color see_color; bool u_has_radio = g->u.has_item_with_flag( "TWO_WAY_RADIO", true ); bool guy_has_radio = has_item_with_flag( "TWO_WAY_RADIO", true ); - // TODO: NPCS on mission contactable same as traveling - if( has_companion_mission() && mission != NPC_MISSION_TRAVELLING ) { - can_see = _( "Not interactable while on a mission" ); - see_color = c_light_red; - // is the NPC even in the same area as the player? - } else if( rl_dist( player_abspos, global_omt_location() ) > 3 || - ( rl_dist( g->u.pos(), pos() ) > SEEX * 2 || !g->u.sees( pos() ) ) ) { + // is the NPC even in the same area as the player? + if( rl_dist( player_abspos, global_omt_location() ) > 3 || + ( rl_dist( g->u.pos(), pos() ) > SEEX * 2 || !g->u.sees( pos() ) ) ) { if( u_has_radio && guy_has_radio ) { // TODO: better range calculation than just elevation. int max_range = 200; @@ -598,6 +594,11 @@ int npc::faction_display( const catacurses::window &fac_w, const int width ) con can_see = _( "Within interaction range" ); see_color = c_light_green; } + // TODO: NPCS on mission contactable same as traveling + if( has_companion_mission() ) { + can_see = _( "Press enter to recall from their mission." ); + see_color = c_light_red; + } mvwprintz( fac_w, point( width, ++y ), see_color, "%s", can_see ); nc_color status_col = col; std::string current_status = _( "Status: " ); @@ -891,11 +892,16 @@ void faction_manager::display() const } else { selection--; } - } else if( action == "CONFIRM" ) { - if( tab == tab_mode::TAB_FOLLOWERS && guy && ( interactable || radio_interactable ) ) { - guy->talk_to_u( false, radio_interactable ); - } else if( tab == tab_mode::TAB_MYFACTION && camp ) { - camp->query_new_name(); + } else if( action == "CONFIRM" && guy ) { + if( guy->has_companion_mission() ) { + guy->reset_companion_mission(); + popup( _( "%s returns from their mission" ), guy->disp_name() ); + } else { + if( tab == tab_mode::TAB_FOLLOWERS && guy && ( interactable || radio_interactable ) ) { + guy->talk_to_u( false, radio_interactable ); + } else if( tab == tab_mode::TAB_MYFACTION && camp ) { + camp->query_new_name(); + } } } else if( action == "QUIT" ) { break; diff --git a/src/game.cpp b/src/game.cpp index da75031fe5502..9dff4a11fec29 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -557,9 +557,6 @@ void game::init_ui( const bool resized ) w_minimap = w_minimap_ptr = catacurses::newwin( MINIMAP_HEIGHT, MINIMAP_WIDTH, point( _x, _y ) ); werase( w_minimap ); - w_panel_adm = w_panel_adm_ptr = catacurses::newwin( 20, 75, point( ( TERMX / 2 ) - 38, - ( TERMY / 2 ) - 10 ) ); - werase( w_panel_adm ); // need to init in order to avoid crash. gets updated by the panel code. w_pixel_minimap = catacurses::newwin( 1, 1, point_zero ); liveview.init(); @@ -595,11 +592,6 @@ void game::toggle_pixel_minimap() #endif // TILES } -void game::toggle_panel_adm() -{ - show_panel_adm = !show_panel_adm; -} - void game::reload_tileset() { #if defined(TILES) @@ -955,7 +947,7 @@ void game::load_npcs() if( temp->is_active() ) { continue; } - if( ( temp->has_companion_mission() ) && ( temp->mission != NPC_MISSION_TRAVELLING ) ) { + if( temp->has_companion_mission() ) { continue; } @@ -3302,11 +3294,6 @@ void game::draw() } void game::draw_panels( bool force_draw ) -{ - draw_panels( 0, 1, force_draw ); -} - -void game::draw_panels( size_t column, size_t index, bool force_draw ) { static int previous_turn = -1; const int current_turn = to_turns( calendar::turn - calendar::turn_zero ); @@ -3361,9 +3348,6 @@ void game::draw_panels( size_t column, size_t index, bool force_draw ) } } } - if( show_panel_adm ) { - mgr.draw_adm( w_panel_adm, column, index ); - } previous_turn = current_turn; } @@ -3635,7 +3619,7 @@ void game::draw_minimap() double slope = ( cursx != targ.x ) ? static_cast( targ.y - cursy ) / static_cast ( targ.x - cursx ) : 4; - if( cursx == targ.x || fabs( slope ) > 3.5 ) { // Vertical slope + if( cursx == targ.x || std::fabs( slope ) > 3.5 ) { // Vertical slope if( targ.y > cursy ) { mvwputch( w_minimap, point( 3, 6 ), c_red, "*" ); } else { @@ -3644,7 +3628,7 @@ void game::draw_minimap() } else { int arrowx = -1; int arrowy = -1; - if( fabs( slope ) >= 1. ) { // y diff is bigger! + if( std::fabs( slope ) >= 1. ) { // y diff is bigger! arrowy = ( targ.y > cursy ? 6 : 0 ); arrowx = static_cast( 3 + 3 * ( targ.y > cursy ? slope : ( 0 - slope ) ) ); if( arrowx < 0 ) { @@ -10701,7 +10685,7 @@ point game::update_map( int &x, int &y ) } } - scent.shift( shift_ms.x, shift_ms.y ); + scent.shift( shift_ms ); // Also ensure the player is on current z-level // get_levz() should later be removed, when there is no longer such a thing @@ -11050,10 +11034,10 @@ void game::perhaps_add_random_npc() float density = get_option( "NPC_DENSITY" ); static constexpr int density_search_radius = 60; - const int npc_num = overmap_buffer.get_npcs_near_player( density_search_radius ).size(); - if( npc_num > 0 ) { + const float npc_num = overmap_buffer.get_npcs_near_player( density_search_radius ).size(); + if( npc_num > 0.0 ) { // 100%, 80%, 64%, 52%, 41%, 33%... - density *= powf( 0.8f, npc_num ); + density *= std::pow( 0.8f, npc_num ); } if( !x_in_y( density, 100 ) ) { @@ -11555,21 +11539,21 @@ void game::start_calendar() if( scen_season ) { // Configured starting date overridden by scenario, calendar::start is left as Spring 1 calendar::start_of_cataclysm = calendar::turn_zero + 1_hours * get_option( "INITIAL_TIME" ); - calendar::turn = calendar::turn_zero + 1_hours * get_option( "INITIAL_TIME" ); + calendar::start_of_game = calendar::turn_zero + 1_hours * get_option( "INITIAL_TIME" ); if( scen->has_flag( "SPR_START" ) ) { calendar::initial_season = SPRING; } else if( scen->has_flag( "SUM_START" ) ) { calendar::initial_season = SUMMER; - calendar::turn += calendar::season_length(); + calendar::start_of_game += calendar::season_length(); } else if( scen->has_flag( "AUT_START" ) ) { calendar::initial_season = AUTUMN; - calendar::turn += calendar::season_length() * 2; + calendar::start_of_game += calendar::season_length() * 2; } else if( scen->has_flag( "WIN_START" ) ) { calendar::initial_season = WINTER; - calendar::turn += calendar::season_length() * 3; + calendar::start_of_game += calendar::season_length() * 3; } else if( scen->has_flag( "SUM_ADV_START" ) ) { calendar::initial_season = SUMMER; - calendar::turn += calendar::season_length() * 5; + calendar::start_of_game += calendar::season_length() * 5; } else { debugmsg( "The Unicorn" ); } @@ -11595,11 +11579,12 @@ void game::start_calendar() calendar::initial_season = WINTER; } - calendar::turn = calendar::start_of_cataclysm - + 1_hours * get_option( "INITIAL_TIME" ) - + 1_days * get_option( "SPAWN_DELAY" ); + calendar::start_of_game = calendar::start_of_cataclysm + + 1_hours * get_option( "INITIAL_TIME" ) + + 1_days * get_option( "SPAWN_DELAY" ); } + calendar::turn = calendar::start_of_game; } void game::add_artifact_messages( const std::vector &effects ) diff --git a/src/game.h b/src/game.h index 73aaa39f11745..105e638d3b615 100644 --- a/src/game.h +++ b/src/game.h @@ -240,9 +240,6 @@ class game // when force_redraw is true, redraw all panel instead of just animated panels // mostly used after UI updates void draw_panels( bool force_draw = false ); - // when force_redraw is true, redraw all panel instead of just animated panels - // mostly used after UI updates - void draw_panels( size_t column, size_t index, bool force_draw = false ); /** * Returns the location where the indicator should go relative to the reality bubble, * or nothing to indicate no indicator should be drawn. @@ -594,7 +591,6 @@ class game void toggle_fullscreen(); void toggle_pixel_minimap(); - void toggle_panel_adm(); void reload_tileset(); void temp_exit_fullscreen(); void reenter_fullscreen(); @@ -975,9 +971,6 @@ class game catacurses::window w_pixel_minimap; //only a pointer, can refer to w_messages_short or w_messages_long - catacurses::window w_panel_adm_ptr; - catacurses::window w_panel_adm; - catacurses::window w_blackspace; // View offset based on the driving speed (if any) diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 36ad9b1b5afac..50ed993b408b3 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -55,6 +55,7 @@ #include "options.h" #include "output.h" #include "overmap_ui.h" +#include "panels.h" #include "player.h" #include "player_activity.h" #include "popup.h" @@ -2366,7 +2367,7 @@ bool game::handle_action() break; case ACTION_TOGGLE_PANEL_ADM: - toggle_panel_adm(); + panel_manager::get_manager().show_adm(); break; case ACTION_RELOAD_TILESET: diff --git a/src/init.cpp b/src/init.cpp index 20b849b257e97..aa97399b02dba 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -616,6 +616,7 @@ void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) { _( "Harvest lists" ), &harvest_list::finalize_all }, { _( "Anatomies" ), &anatomy::finalize_all }, { _( "Mutations" ), &mutation_branch::finalize }, + { _( "Achivements" ), &achievement::finalize }, #if defined(TILES) { _( "Tileset" ), &load_tileset }, #endif diff --git a/src/input.h b/src/input.h index 858487b773089..bbde236c5030f 100644 --- a/src/input.h +++ b/src/input.h @@ -115,14 +115,14 @@ struct input_event { int shortcut_last_used_action_counter; #endif - input_event() { + input_event() : edit_refresh( false ) { type = CATA_INPUT_ERROR; #if defined(__ANDROID__) shortcut_last_used_action_counter = 0; #endif } input_event( int s, input_event_t t ) - : type( t ) { + : type( t ), edit_refresh( false ) { sequence.push_back( s ); #if defined(__ANDROID__) shortcut_last_used_action_counter = 0; @@ -387,7 +387,7 @@ class input_context #endif input_context() : registered_any_input( false ), category( "default" ), - handling_coordinate_input( false ) { + coordinate_input_received( false ), handling_coordinate_input( false ) { #if defined(__ANDROID__) input_context_stack.push_back( this ); allow_text_entry = false; @@ -396,7 +396,7 @@ class input_context // TODO: consider making the curses WINDOW an argument to the constructor, so that mouse input // outside that window can be ignored input_context( const std::string &category ) : registered_any_input( false ), - category( category ), handling_coordinate_input( false ) { + category( category ), coordinate_input_received( false ), handling_coordinate_input( false ) { #if defined(__ANDROID__) input_context_stack.push_back( this ); allow_text_entry = false; diff --git a/src/item.cpp b/src/item.cpp index 1b62406b649f5..14271213ac0b0 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -1678,8 +1678,8 @@ void item::food_info( const item *food_item, std::vector &info, const double multiplier = g->u.vitamin_rate( v.first ) / 1_days * 100; const int min_value = min_nutr.get_vitamin( v.first ); const int max_value = v.second; - const int min_rda = lround( min_value * multiplier ); - const int max_rda = lround( max_value * multiplier ); + const int min_rda = std::lround( min_value * multiplier ); + const int max_rda = std::lround( max_value * multiplier ); const std::string format = min_rda == max_rda ? "%s (%i%%)" : "%s (%i-%i%%)"; return string_format( format, v.first->name(), min_value, max_value ); }; @@ -5209,7 +5209,7 @@ static int calc_hourly_rotpoints_at_temp( const int temp ) } else if( temp < dropoff ) { return ( temp - temperatures::freezing ) * dstep; } else { - return lround( 215.46 * std::pow( 2.0, static_cast( temp ) / 16.0 ) ); + return std::lround( 215.46 * std::pow( 2.0, static_cast( temp ) / 16.0 ) ); } } @@ -5310,7 +5310,7 @@ units::volume item::get_storage() const } units::volume storage = t->storage; float mod = get_clothing_mod_val( clothing_mod_type_storage ); - storage += lround( mod ) * units::legacy_volume_factor; + storage += std::lround( mod ) * units::legacy_volume_factor; return storage; } @@ -5629,7 +5629,7 @@ int item::bash_resist( bool to_self ) const resist /= mat_types.size(); } - return lround( ( resist * eff_thickness ) + mod ); + return std::lround( ( resist * eff_thickness ) + mod ); } int item::cut_resist( bool to_self ) const @@ -5658,7 +5658,7 @@ int item::cut_resist( bool to_self ) const resist /= mat_types.size(); } - return lround( ( resist * eff_thickness ) + mod ); + return std::lround( ( resist * eff_thickness ) + mod ); } #if defined(_MSC_VER) @@ -5702,7 +5702,7 @@ int item::acid_resist( bool to_self, int base_env_resist ) const resist *= env / 10.0f; } - return lround( resist + mod ); + return std::lround( resist + mod ); } int item::fire_resist( bool to_self, int base_env_resist ) const @@ -5733,7 +5733,7 @@ int item::fire_resist( bool to_self, int base_env_resist ) const resist *= env / 10.0f; } - return lround( resist + mod ); + return std::lround( resist + mod ); } int item::chip_resistance( bool worst ) const @@ -8167,8 +8167,8 @@ void item::set_item_specific_energy( const float new_specific_energy ) } else if( new_item_temperature < temp_to_kelvin( temperatures::cold ) ) { item_tags.insert( "COLD" ); } - temperature = lround( 100000 * new_item_temperature ); - specific_energy = lround( 100000 * new_specific_energy ); + temperature = std::lround( 100000 * new_item_temperature ); + specific_energy = std::lround( 100000 * new_specific_energy ); reset_temp_check(); } @@ -8202,8 +8202,8 @@ void item::set_item_temperature( float new_temperature ) float new_specific_energy = get_specific_energy_from_temperature( new_temperature ); float freeze_percentage = 0; - temperature = lround( 100000 * new_temperature ); - specific_energy = lround( 100000 * new_specific_energy ); + temperature = std::lround( 100000 * new_temperature ); + specific_energy = std::lround( 100000 * new_specific_energy ); const float completely_frozen_specific_energy = specific_heat_solid * freezing_temperature; // Energy that the item would have if it was completely solid at freezing temperature @@ -8972,8 +8972,8 @@ void item::calc_temp( const int temp, const float insulation, const time_point & } else if( new_item_temperature < temp_to_kelvin( temperatures::cold ) ) { item_tags.insert( "COLD" ); } - temperature = lround( 100000 * new_item_temperature ); - specific_energy = lround( 100000 * new_specific_energy ); + temperature = std::lround( 100000 * new_item_temperature ); + specific_energy = std::lround( 100000 * new_specific_energy ); last_temp_check = time; } @@ -8993,7 +8993,7 @@ void item::heat_up() // Set item temperature to 60 C (333.15 K, 122 F) // Also set the energy to match temperature = 333.15 * 100000; - specific_energy = lround( 100000 * get_specific_energy_from_temperature( 333.15 ) ); + specific_energy = std::lround( 100000 * get_specific_energy_from_temperature( 333.15 ) ); reset_temp_check(); } @@ -9007,7 +9007,7 @@ void item::cold_up() // Set item temperature to 3 C (276.15 K, 37.4 F) // Also set the energy to match temperature = 276.15 * 100000; - specific_energy = lround( 100000 * get_specific_energy_from_temperature( 276.15 ) ); + specific_energy = std::lround( 100000 * get_specific_energy_from_temperature( 276.15 ) ); reset_temp_check(); } diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 82aa9cca33f91..df01a47d72357 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -2253,26 +2253,13 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: "TOOL_ARMOR", "WHEEL", }; - if( jo.has_member( "name_plural" ) ) { - if( needs_plural.find( jo.get_string( "type" ) ) == needs_plural.end() ) { - try { - jo.throw_error( "name_plural not allowed for this object type", "name_plural" ); - } catch( const JsonError &e ) { - debugmsg( "\n%s", e.what() ); - } - } - // legacy format - // NOLINTNEXTLINE(cata-json-translation-input) - def.name = pl_translation( jo.get_string( "name" ), jo.get_string( "name_plural" ) ); + if( needs_plural.find( jo.get_string( "type" ) ) != needs_plural.end() ) { + def.name = translation( translation::plural_tag() ); } else { - if( needs_plural.find( jo.get_string( "type" ) ) != needs_plural.end() ) { - def.name = translation( translation::plural_tag() ); - } else { - def.name = translation(); - } - if( !jo.read( "name", def.name ) ) { - jo.throw_error( "name unspecified for item type" ); - } + def.name = translation(); + } + if( !jo.read( "name", def.name ) ) { + jo.throw_error( "name unspecified for item type" ); } if( jo.has_member( "description" ) ) { diff --git a/src/lightmap.cpp b/src/lightmap.cpp index ff0217154601f..23e1f63639dbf 100644 --- a/src/lightmap.cpp +++ b/src/lightmap.cpp @@ -1421,15 +1421,15 @@ void map::apply_light_arc( const tripoint &p, int angle, float luminance, int wi if( trigdist ) { double fdist = ( ao * M_PI_2 ) / wangle; double orad = ( M_PI * ao / 180.0 ); - end.x = static_cast( p.x + ( static_cast( range ) - fdist * 2.0 ) * cos( + end.x = static_cast( p.x + ( static_cast( range ) - fdist * 2.0 ) * std::cos( rad + orad ) ); - end.y = static_cast( p.y + ( static_cast( range ) - fdist * 2.0 ) * sin( + end.y = static_cast( p.y + ( static_cast( range ) - fdist * 2.0 ) * std::sin( rad + orad ) ); apply_light_ray( lit, p, end, luminance ); - end.x = static_cast( p.x + ( static_cast( range ) - fdist * 2.0 ) * cos( + end.x = static_cast( p.x + ( static_cast( range ) - fdist * 2.0 ) * std::cos( rad - orad ) ); - end.y = static_cast( p.y + ( static_cast( range ) - fdist * 2.0 ) * sin( + end.y = static_cast( p.y + ( static_cast( range ) - fdist * 2.0 ) * std::sin( rad - orad ) ); apply_light_ray( lit, p, end, luminance ); } else { diff --git a/src/lightmap.h b/src/lightmap.h index 8df48f6273a52..6a16e3ee6379d 100644 --- a/src/lightmap.h +++ b/src/lightmap.h @@ -23,7 +23,7 @@ #define LIGHT_TRANSPARENCY_OPEN_AIR 0.038376418216 #define LIGHT_TRANSPARENCY_CLEAR 1 -#define LIGHT_RANGE(b) static_cast( -log(LIGHT_AMBIENT_LOW / static_cast(b)) * (1.0 / LIGHT_TRANSPARENCY_OPEN_AIR) ) +#define LIGHT_RANGE(b) static_cast( -std::log(LIGHT_AMBIENT_LOW / static_cast(b)) * (1.0 / LIGHT_TRANSPARENCY_OPEN_AIR) ) enum lit_level { LL_DARK = 0, diff --git a/src/line.cpp b/src/line.cpp index 61b0d6a88a2b8..1087dd135ff75 100644 --- a/src/line.cpp +++ b/src/line.cpp @@ -608,16 +608,16 @@ rl_vec3d rl_vec3d::normalized() const rl_vec2d rl_vec2d::rotated( float angle ) const { return rl_vec2d( - x * cos( angle ) - y * sin( angle ), - x * sin( angle ) + y * cos( angle ) + x * std::cos( angle ) - y * std::sin( angle ), + x * std::sin( angle ) + y * std::cos( angle ) ); } rl_vec3d rl_vec3d::rotated( float angle ) const { return rl_vec3d( - x * cos( angle ) - y * sin( angle ), - x * sin( angle ) + y * cos( angle ) + x * std::cos( angle ) - y * std::sin( angle ), + x * std::sin( angle ) + y * std::cos( angle ) ); } @@ -756,8 +756,8 @@ void calc_ray_end( int angle, const int range, const tripoint &p, tripoint &out const double rad = DEGREES( angle ); out.z = p.z; if( trigdist ) { - out.x = p.x + range * cos( rad ); - out.y = p.y + range * sin( rad ); + out.x = p.x + range * std::cos( rad ); + out.y = p.y + range * std::sin( rad ); } else { int mult = 0; if( angle >= 135 && angle <= 315 ) { @@ -768,9 +768,9 @@ void calc_ray_end( int angle, const int range, const tripoint &p, tripoint &out if( angle <= 45 || ( 135 <= angle && angle <= 215 ) || 315 < angle ) { out.x = p.x + range * mult; - out.y = p.y + range * tan( rad ) * mult; + out.y = p.y + range * std::tan( rad ) * mult; } else { - out.x = p.x + range * 1 / tan( rad ) * mult; + out.x = p.x + range * 1 / std::tan( rad ) * mult; out.y = p.y + range * mult; } } diff --git a/src/line.h b/src/line.h index 2e195ca57e194..88a12bc9bf7fb 100644 --- a/src/line.h +++ b/src/line.h @@ -34,7 +34,7 @@ constexpr double ARCMIN( double v ) inline double iso_tangent( double distance, double vertex ) { // we can use the cosine formula (a² = b² + c² - 2bc⋅cosθ) to calculate the tangent - return std::sqrt( 2 * std::pow( distance, 2 ) * ( 1 - cos( ARCMIN( vertex ) ) ) ); + return std::sqrt( 2 * std::pow( distance, 2 ) * ( 1 - std::cos( ARCMIN( vertex ) ) ) ); } //! This compile-time usable function combines the sign of each (x, y, z) component into a single integer diff --git a/src/map.cpp b/src/map.cpp index b355591fdeff4..3fc1796975df3 100755 --- a/src/map.cpp +++ b/src/map.cpp @@ -553,7 +553,7 @@ vehicle *map::move_vehicle( vehicle &veh, const tripoint &dp, const tileray &fac int coll_turn = 0; if( impulse > 0 ) { coll_turn = shake_vehicle( veh, velocity_before, facing.dir() ); - const int volume = std::min( 100, sqrtf( impulse ) ); + const int volume = std::min( 100, std::sqrt( impulse ) ); // TODO: Center the sound at weighted (by impulse) average of collisions sounds::sound( veh.global_pos3(), volume, sounds::sound_t::combat, _( "crash!" ), false, "smash_success", "hit_vehicle" ); diff --git a/src/map_extras.cpp b/src/map_extras.cpp index 207750f9a3aa5..7b6b0876d88af 100644 --- a/src/map_extras.cpp +++ b/src/map_extras.cpp @@ -267,7 +267,7 @@ static bool mx_house_spider( map &m, const tripoint &loc ) for( int x = i - 1; x <= i + 1; x++ ) { for( int y = j - 1; y <= j + 1; y++ ) { if( m.ter( point( x, y ) ) == t_floor ) { - madd_field( &m, x, y, fd_web, rng( 2, 3 ) ); + madd_field( &m, point( x, y ), fd_web, rng( 2, 3 ) ); if( one_in( 4 ) ) { m.furn_set( point( i, j ), egg_type ); m.remove_field( {i, j, m.get_abs_sub().z}, fd_web ); @@ -276,7 +276,7 @@ static bool mx_house_spider( map &m, const tripoint &loc ) } } } else if( m.passable( point( i, j ) ) && one_in( 5 ) ) { - madd_field( &m, i, j, fd_web, 1 ); + madd_field( &m, point( i, j ), fd_web, 1 ); } } } @@ -1092,9 +1092,9 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) for( int i = 0; i < num_mines; i++ ) { const int x = rng( 3, SEEX * 2 - 4 ), y = rng( SEEY, SEEY * 2 - 2 ); if( m.has_flag( flag_DIGGABLE, point( x, y ) ) ) { - mtrap_set( &m, x, y, tr_landmine_buried ); + mtrap_set( &m, point( x, y ), tr_landmine_buried ); } else { - mtrap_set( &m, x, y, tr_landmine ); + mtrap_set( &m, point( x, y ), tr_landmine ); } } @@ -1193,9 +1193,9 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) for( int i = 0; i < num_mines; i++ ) { const int x = rng( 3, SEEX * 2 - 4 ), y = rng( 1, SEEY ); if( m.has_flag( flag_DIGGABLE, point( x, y ) ) ) { - mtrap_set( &m, x, y, tr_landmine_buried ); + mtrap_set( &m, point( x, y ), tr_landmine_buried ); } else { - mtrap_set( &m, x, y, tr_landmine ); + mtrap_set( &m, point( x, y ), tr_landmine ); } } @@ -1339,9 +1339,9 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) for( int i = 0; i < num_mines; i++ ) { const int x = rng( SEEX + 1, SEEX * 2 - 2 ), y = rng( 3, SEEY * 2 - 4 ); if( m.has_flag( flag_DIGGABLE, point( x, y ) ) ) { - mtrap_set( &m, x, y, tr_landmine_buried ); + mtrap_set( &m, point( x, y ), tr_landmine_buried ); } else { - mtrap_set( &m, x, y, tr_landmine ); + mtrap_set( &m, point( x, y ), tr_landmine ); } } @@ -1473,9 +1473,9 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) for( int i = 0; i < num_mines; i++ ) { const int x = rng( 1, SEEX ), y = rng( 3, SEEY * 2 - 4 ); if( m.has_flag( flag_DIGGABLE, point( x, y ) ) ) { - mtrap_set( &m, x, y, tr_landmine_buried ); + mtrap_set( &m, point( x, y ), tr_landmine_buried ); } else { - mtrap_set( &m, x, y, tr_landmine ); + mtrap_set( &m, point( x, y ), tr_landmine ); } } diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 5cdb8ff32aec8..8a482590b20ad 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -2542,7 +2542,7 @@ bool jmapgen_setmap::apply( mapgendata &dat, const point &offset ) const break; case JMAPGEN_SETMAP_TRAP: { // TODO: the trap_id should be stored separately and not be wrapped in an jmapgen_int - mtrap_set( &m, x_get(), y_get(), trap_id( val.get() ) ); + mtrap_set( &m, point( x_get(), y_get() ), trap_id( val.get() ) ); } break; case JMAPGEN_SETMAP_RADIATION: { @@ -2569,7 +2569,7 @@ bool jmapgen_setmap::apply( mapgendata &dat, const point &offset ) const 0 ); for( auto &i : line ) { // TODO: the trap_id should be stored separately and not be wrapped in an jmapgen_int - mtrap_set( &m, i.x, i.y, trap_id( val.get() ) ); + mtrap_set( &m, i, trap_id( val.get() ) ); } } break; @@ -2599,7 +2599,7 @@ bool jmapgen_setmap::apply( mapgendata &dat, const point &offset ) const for( int tx = cx; tx <= cx2; tx++ ) { for( int ty = cy; ty <= cy2; ty++ ) { // TODO: the trap_id should be stored separately and not be wrapped in an jmapgen_int - mtrap_set( &m, tx, ty, trap_id( val.get() ) ); + mtrap_set( &m, point( tx, ty ), trap_id( val.get() ) ); } } } @@ -4241,10 +4241,10 @@ void map::draw_lab( mapgendata &dat ) point( SEEX * 2 - 7, SEEY * 2 - 7 ), 1, true ); spawn_item( point( SEEX - 4, SEEY - 2 ), "id_science" ); if( loot_variant <= 96 ) { - mtrap_set( this, SEEX - 3, SEEY - 3, tr_dissector ); - mtrap_set( this, SEEX + 2, SEEY - 3, tr_dissector ); - mtrap_set( this, SEEX - 3, SEEY + 2, tr_dissector ); - mtrap_set( this, SEEX + 2, SEEY + 2, tr_dissector ); + mtrap_set( this, point( SEEX - 3, SEEY - 3 ), tr_dissector ); + mtrap_set( this, point( SEEX + 2, SEEY - 3 ), tr_dissector ); + mtrap_set( this, point( SEEX - 3, SEEY + 2 ), tr_dissector ); + mtrap_set( this, point( SEEX + 2, SEEY + 2 ), tr_dissector ); line( this, t_reinforced_glass, point( SEEX + 1, SEEY + 1 ), point( SEEX - 2, SEEY + 1 ) ); line( this, t_reinforced_glass, point( SEEX - 2, SEEY ), point( SEEX - 2, SEEY - 2 ) ); line( this, t_reinforced_glass, point( SEEX - 1, SEEY - 2 ), point( SEEX + 1, SEEY - 2 ) ); @@ -4277,10 +4277,10 @@ void map::draw_lab( mapgendata &dat ) spawn_item( point( SEEX, SEEY ), "recipe_caseless" ); } } else { // 4% of the lab ends will be this weapons testing end. - mtrap_set( this, SEEX - 4, SEEY - 3, tr_dissector ); - mtrap_set( this, SEEX + 3, SEEY - 3, tr_dissector ); - mtrap_set( this, SEEX - 4, SEEY + 2, tr_dissector ); - mtrap_set( this, SEEX + 3, SEEY + 2, tr_dissector ); + mtrap_set( this, point( SEEX - 4, SEEY - 3 ), tr_dissector ); + mtrap_set( this, point( SEEX + 3, SEEY - 3 ), tr_dissector ); + mtrap_set( this, point( SEEX - 4, SEEY + 2 ), tr_dissector ); + mtrap_set( this, point( SEEX + 3, SEEY + 2 ), tr_dissector ); furn_set( point( SEEX - 2, SEEY - 1 ), f_rack ); furn_set( point( SEEX - 1, SEEY - 1 ), f_rack ); @@ -4360,10 +4360,10 @@ void map::draw_lab( mapgendata &dat ) point( 6, SEEY * 2 - 7 ), 1, true ); place_spawns( GROUP_ROBOT_SECUBOT, 1, point( SEEX * 2 - 7, SEEY * 2 - 7 ), point( SEEX * 2 - 7, SEEY * 2 - 7 ), 1, true ); - mtrap_set( this, SEEX - 2, SEEY - 2, tr_dissector ); - mtrap_set( this, SEEX + 1, SEEY - 2, tr_dissector ); - mtrap_set( this, SEEX - 2, SEEY + 1, tr_dissector ); - mtrap_set( this, SEEX + 1, SEEY + 1, tr_dissector ); + mtrap_set( this, point( SEEX - 2, SEEY - 2 ), tr_dissector ); + mtrap_set( this, point( SEEX + 1, SEEY - 2 ), tr_dissector ); + mtrap_set( this, point( SEEX - 2, SEEY + 1 ), tr_dissector ); + mtrap_set( this, point( SEEX + 1, SEEY + 1 ), tr_dissector ); square_furn( this, f_counter, point( SEEX - 1, SEEY - 1 ), point( SEEX, SEEY ) ); int item_count = 0; while( item_count < 5 ) { @@ -4491,12 +4491,12 @@ void map::draw_temple( mapgendata &dat ) square( this, t_rock, point( 0, SEEY * 2 - 2 ), point( SEEX - 1, SOUTH_EDGE ) ); square( this, t_rock, point( SEEX + 2, SEEY * 2 - 2 ), point( EAST_EDGE, SOUTH_EDGE ) ); line( this, t_grate, point( SEEX, 1 ), point( SEEX + 1, 1 ) ); // To drain the water - mtrap_set( this, SEEX, SEEY * 2 - 2, tr_temple_flood ); - mtrap_set( this, SEEX + 1, SEEY * 2 - 2, tr_temple_flood ); + mtrap_set( this, point( SEEX, SEEY * 2 - 2 ), tr_temple_flood ); + mtrap_set( this, point( SEEX + 1, SEEY * 2 - 2 ), tr_temple_flood ); for( int y = 2; y < SEEY * 2 - 2; y++ ) { for( int x = 2; x < SEEX * 2 - 2; x++ ) { if( ter( point( x, y ) ) == t_rock_floor && one_in( 4 ) ) { - mtrap_set( this, x, y, tr_temple_flood ); + mtrap_set( this, point( x, y ), tr_temple_flood ); } } } @@ -4656,7 +4656,7 @@ void map::draw_temple( mapgendata &dat ) // Finally, fill in the rest with random tiles, and place toggle traps for( int i = SEEX - 3; i <= SEEX + 4; i++ ) { for( int j = 2; j <= SEEY * 2 - 2; j++ ) { - mtrap_set( this, i, j, tr_temple_toggle ); + mtrap_set( this, point( i, j ), tr_temple_toggle ); if( ter( point( i, j ) ) == t_rock_floor ) { static const std::vector terrains = { t_rock_red, t_rock_green, t_rock_blue, @@ -6502,31 +6502,31 @@ void science_room( map *m, int x1, int y1, int x2, int y2, int z, int rotate ) m->furn_set( point( static_cast( ( x1 + x2 ) / 2 ) + 1, static_cast( ( y1 + y2 ) / 2 ) + 1 ), f_counter ); - mtrap_set( m, trapx, trapy, tr_telepad ); + mtrap_set( m, point( trapx, trapy ), tr_telepad ); m->place_items( "teleport", 70, point( ( x1 + x2 ) / 2, static_cast( ( y1 + y2 ) / 2 ) ), point( static_cast( ( x1 + x2 ) / 2 ) + 1, static_cast( ( y1 + y2 ) / 2 ) + 1 ), false, calendar::start_of_cataclysm ); break; case room_goo: do { - mtrap_set( m, trapx, trapy, tr_goo ); + mtrap_set( m, point( trapx, trapy ), tr_goo ); trapx = rng( x1 + 1, x2 - 1 ); trapy = rng( y1 + 1, y2 - 1 ); } while( !one_in( 5 ) ); if( rotate == 0 ) { - mremove_trap( m, x1, y2 ); + mremove_trap( m, point( x1, y2 ) ); m->furn_set( point( x1, y2 ), f_fridge ); m->place_items( "goo", 60, point( x1, y2 ), point( x1, y2 ), false, calendar::start_of_cataclysm ); } else if( rotate == 1 ) { - mremove_trap( m, x1, y1 ); + mremove_trap( m, point( x1, y1 ) ); m->furn_set( point( x1, y1 ), f_fridge ); m->place_items( "goo", 60, point( x1, y1 ), point( x1, y1 ), false, calendar::start_of_cataclysm ); } else if( rotate == 2 ) { - mremove_trap( m, x2, y1 ); + mremove_trap( m, point( x2, y1 ) ); m->furn_set( point( x2, y1 ), f_fridge ); m->place_items( "goo", 60, point( x2, y1 ), point( x2, y1 ), false, calendar::start_of_cataclysm ); } else { - mremove_trap( m, x2, y2 ); + mremove_trap( m, point( x2, y2 ) ); m->furn_set( point( x2, y2 ), f_fridge ); m->place_items( "goo", 60, point( x2, y2 ), point( x2, y2 ), false, calendar::start_of_cataclysm ); } @@ -6568,7 +6568,7 @@ void science_room( map *m, int x1, int y1, int x2, int y2, int z, int rotate ) m->place_items( "dissection", 80, point( x2 - 1, y1 ), point( x2 - 1, y2 ), false, calendar::start_of_cataclysm ); } - mtrap_set( m, static_cast( ( x1 + x2 ) / 2 ), static_cast( ( y1 + y2 ) / 2 ), + mtrap_set( m, point( ( x1 + x2 ) / 2, static_cast( ( y1 + y2 ) / 2 ) ), tr_dissector ); m->place_spawns( GROUP_LAB_CYBORG, 10, point( static_cast( ( ( x1 + x2 ) / 2 ) + 1 ), @@ -7065,7 +7065,7 @@ void map::create_anomaly( const tripoint &cp, artifact_natural_property prop, bo for( int i = cx - 5; i <= cx + 5; i++ ) { for( int j = cy - 5; j <= cy + 5; j++ ) { if( furn( point( i, j ) ) == f_rubble && one_in( 2 ) ) { - mtrap_set( this, i, j, tr_glow ); + mtrap_set( this, point( i, j ), tr_glow ); } } } @@ -7076,7 +7076,7 @@ void map::create_anomaly( const tripoint &cp, artifact_natural_property prop, bo for( int i = cx - 5; i <= cx + 5; i++ ) { for( int j = cy - 5; j <= cy + 5; j++ ) { if( furn( point( i, j ) ) == f_rubble && one_in( 2 ) ) { - mtrap_set( this, i, j, tr_hum ); + mtrap_set( this, point( i, j ), tr_hum ); } } } @@ -7087,7 +7087,7 @@ void map::create_anomaly( const tripoint &cp, artifact_natural_property prop, bo for( int i = cx - 5; i <= cx + 5; i++ ) { for( int j = cy - 5; j <= cy + 5; j++ ) { if( furn( point( i, j ) ) == f_rubble && one_in( 3 ) ) { - mtrap_set( this, i, j, tr_shadow ); + mtrap_set( this, point( i, j ), tr_shadow ); } } } @@ -7110,7 +7110,7 @@ void map::create_anomaly( const tripoint &cp, artifact_natural_property prop, bo for( int i = cx - 5; i <= cx + 5; i++ ) { for( int j = cy - 5; j <= cy + 5; j++ ) { if( furn( point( i, j ) ) == f_rubble ) { - mtrap_set( this, i, j, tr_drain ); + mtrap_set( this, point( i, j ), tr_drain ); } } } @@ -7149,7 +7149,7 @@ void map::create_anomaly( const tripoint &cp, artifact_natural_property prop, bo for( int i = cx - 5; i <= cx + 5; i++ ) { for( int j = cy - 5; j <= cy + 5; j++ ) { if( furn( point( i, j ) ) == f_rubble ) { - mtrap_set( this, i, j, tr_snake ); + mtrap_set( this, point( i, j ), tr_snake ); } } } diff --git a/src/mapgen_functions.cpp b/src/mapgen_functions.cpp index 286a8d1b3418f..94e43801225e4 100644 --- a/src/mapgen_functions.cpp +++ b/src/mapgen_functions.cpp @@ -484,11 +484,11 @@ void mapgen_spider_pit( mapgendata &dat ) m->ter_set( point( x, y ), t_slope_down ); } else { m->ter_set( point( x, y ), dat.groundcover() ); - mtrap_set( m, x, y, tr_sinkhole ); + mtrap_set( m, point( x, y ), tr_sinkhole ); } for( int x1 = x - 3; x1 <= x + 3; x1++ ) { for( int y1 = y - 3; y1 <= y + 3; y1++ ) { - madd_field( m, x1, y1, fd_web, rng( 2, 3 ) ); + madd_field( m, point( x1, y1 ), fd_web, rng( 2, 3 ) ); if( m->ter( point( x1, y1 ) ) != t_slope_down ) { m->ter_set( point( x1, y1 ), t_dirt ); } @@ -1935,7 +1935,7 @@ void mapgen_cave_rat( mapgendata &dat ) for( int cy = cavey - 1; cy <= cavey + 1; cy++ ) { m->ter_set( point( cx, cy ), t_rock_floor ); if( one_in( 10 ) ) { - madd_field( m, cx, cy, fd_blood, rng( 1, 3 ) ); + madd_field( m, point( cx, cy ), fd_blood, rng( 1, 3 ) ); } if( one_in( 20 ) ) { m->add_spawn( mon_sewer_rat, 1, { cx, cy, m->get_abs_sub().z } ); @@ -1955,7 +1955,7 @@ void mapgen_cave_rat( mapgendata &dat ) for( int cy = i.y - 1; cy <= i.y + 1; cy++ ) { m->ter_set( point( cx, cy ), t_rock_floor ); if( one_in( 10 ) ) { - madd_field( m, cx, cy, fd_blood, rng( 1, 3 ) ); + madd_field( m, point( cx, cy ), fd_blood, rng( 1, 3 ) ); } if( one_in( 20 ) ) { m->add_spawn( mon_sewer_rat, 1, { cx, cy, m->get_abs_sub().z } ); @@ -3410,21 +3410,21 @@ void mapgen_lake_shore( mapgendata &dat ) m->translate( t_null, t_water_sh ); } -void mremove_trap( map *m, int x, int y ) +void mremove_trap( map *m, const point &p ) { - tripoint actual_location( x, y, m->get_abs_sub().z ); + tripoint actual_location( p, m->get_abs_sub().z ); m->remove_trap( actual_location ); } -void mtrap_set( map *m, int x, int y, trap_id type ) +void mtrap_set( map *m, const point &p, trap_id type ) { - tripoint actual_location( x, y, m->get_abs_sub().z ); + tripoint actual_location( p, m->get_abs_sub().z ); m->trap_set( actual_location, type ); } -void madd_field( map *m, int x, int y, field_type_id type, int intensity ) +void madd_field( map *m, const point &p, field_type_id type, int intensity ) { - tripoint actual_location( x, y, m->get_abs_sub().z ); + tripoint actual_location( p, m->get_abs_sub().z ); m->add_field( actual_location, type, intensity, 0_turns ); } diff --git a/src/mapgen_functions.h b/src/mapgen_functions.h index e83d54bbc067b..004d7919bdb4a 100644 --- a/src/mapgen_functions.h +++ b/src/mapgen_functions.h @@ -12,6 +12,7 @@ class map; class mapgendata; class mission; +struct point; struct tripoint; using mapgen_update_func = std::function; @@ -75,9 +76,9 @@ void mapgen_tutorial( mapgendata &dat ); void mapgen_lake_shore( mapgendata &dat ); // Temporary wrappers -void mremove_trap( map *m, int x, int y ); -void mtrap_set( map *m, int x, int y, trap_id type ); -void madd_field( map *m, int x, int y, field_type_id type, int intensity ); +void mremove_trap( map *m, const point & ); +void mtrap_set( map *m, const point &, trap_id type ); +void madd_field( map *m, const point &, field_type_id type, int intensity ); mapgen_update_func add_mapgen_update_func( const JsonObject &jo, bool &defer ); bool run_mapgen_update_func( const std::string &update_mapgen_id, const tripoint &omt_pos, diff --git a/src/mapgendata.cpp b/src/mapgendata.cpp index e6bd2004dddde..64b54a7f51dbe 100644 --- a/src/mapgendata.cpp +++ b/src/mapgendata.cpp @@ -112,9 +112,9 @@ int &mapgendata::dir( int dir_in ) } } -void mapgendata::square_groundcover( const int x1, const int y1, const int x2, const int y2 ) +void mapgendata::square_groundcover( const point &p1, const point &p2 ) { - m.draw_square_ter( default_groundcover, point( x1, y1 ), point( x2, y2 ) ); + m.draw_square_ter( default_groundcover, p1, p2 ); } void mapgendata::fill_groundcover() diff --git a/src/mapgendata.h b/src/mapgendata.h index 76bc04a0a288c..e7f0162c80749 100644 --- a/src/mapgendata.h +++ b/src/mapgendata.h @@ -6,6 +6,7 @@ #include "calendar.h" #include "weighted_list.h" +struct point; struct tripoint; class mission; struct regional_settings; @@ -133,7 +134,7 @@ class mapgendata } const oter_id &neighbor_at( om_direction::type dir ) const; void fill_groundcover(); - void square_groundcover( int x1, int y1, int x2, int y2 ); + void square_groundcover( const point &p1, const point &p2 ); ter_id groundcover(); bool is_groundcover( const ter_id &iid ) const; }; diff --git a/src/mongroup.h b/src/mongroup.h index 9b9dc25dd52b3..5d3bf1a0e4e61 100644 --- a/src/mongroup.h +++ b/src/mongroup.h @@ -107,10 +107,6 @@ struct mongroup { , radius( prad ) , population( ppop ) { } - mongroup( const mongroup_id &ptype, int pposx, int pposy, int pposz, - unsigned int prad, unsigned int ppop ) - : mongroup( ptype, tripoint( pposx, pposy, pposz ), prad, ppop ) - {} mongroup( const std::string &ptype, tripoint ppos, unsigned int prad, unsigned int ppop, tripoint ptarget, int pint, bool pdie, bool phorde, bool pdiff ) : type( ptype ), pos( ppos ), radius( prad ), population( ppop ), target( ptarget ), @@ -119,9 +115,9 @@ struct mongroup { bool is_safe() const; bool empty() const; void clear(); - void set_target( int x, int y ) { - target.x = x; - target.y = y; + void set_target( const point &p ) { + target.x = p.x; + target.y = p.y; } void wander( const overmap & ); void inc_interest( int inc ) { diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 2c45b4cb6faf1..d324029def0af 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -659,14 +659,9 @@ void mtype::load( const JsonObject &jo, const std::string &src ) MonsterGenerator &gen = MonsterGenerator::generator(); - if( jo.has_string( "name_plural" ) && jo.has_string( "name" ) ) { - // Legacy format - // NOLINTNEXTLINE(cata-json-translation-input) - name = pl_translation( jo.get_string( "name" ), jo.get_string( "name_plural" ) ); - } else { - name.make_plural(); - mandatory( jo, was_loaded, "name", name ); - } + name.make_plural(); + mandatory( jo, was_loaded, "name", name ); + optional( jo, was_loaded, "description", description ); optional( jo, was_loaded, "material", mat, auto_flags_reader {} ); diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index ca4f3fba1a071..482b265b247f6 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -531,7 +531,13 @@ bool avatar::create( character_type type, const std::string &tempname ) for( mtype_id elem : prof->pets() ) { starting_pets.push_back( elem ); } - starting_vehicle = prof->vehicle(); + + if( g->scen->vehicle() != vproto_id::NULL_ID() ) { + starting_vehicle = g->scen->vehicle(); + } else { + starting_vehicle = prof->vehicle(); + } + std::list prof_items = prof->items( male, get_mutations() ); for( item &it : prof_items ) { @@ -1935,6 +1941,7 @@ tab_direction set_scenario( avatar &u, points_left &points, catacurses::window w_sorting; catacurses::window w_profession; catacurses::window w_location; + catacurses::window w_vehicle; catacurses::window w_flags; const auto init_windows = [&]( ui_adaptor & ui ) { iContentHeight = TERMY - 10; @@ -1943,9 +1950,10 @@ tab_direction set_scenario( avatar &u, points_left &points, w_sorting = catacurses::newwin( 2, ( TERMX / 2 ) - 1, point( TERMX / 2, 5 ) ); w_profession = catacurses::newwin( 4, ( TERMX / 2 ) - 1, point( TERMX / 2, 7 ) ); w_location = catacurses::newwin( 3, ( TERMX / 2 ) - 1, point( TERMX / 2, 11 ) ); - // 9 = 2 + 4 + 3, so we use rest of space for flags - w_flags = catacurses::newwin( iContentHeight - 9, ( TERMX / 2 ) - 1, - point( TERMX / 2, 14 ) ); + w_vehicle = catacurses::newwin( 3, ( TERMX / 2 ) - 1, point( TERMX / 2, 14 ) ); + // 11 = 2 + 4 + 3 + 3, so we use rest of space for flags + w_flags = catacurses::newwin( iContentHeight - 14, ( TERMX / 2 ) - 1, + point( TERMX / 2, 17 ) ); ui.position_from_window( w ); }; init_windows( ui ); @@ -2069,6 +2077,7 @@ tab_direction set_scenario( avatar &u, points_left &points, werase( w_sorting ); werase( w_profession ); werase( w_location ); + werase( w_vehicle ); werase( w_flags ); if( cur_id_is_valid ) { @@ -2100,6 +2109,12 @@ tab_direction set_scenario( avatar &u, points_left &points, sorted_scens[cur_id]->start_location_count(), sorted_scens[cur_id]->start_location_targets_count() ) ); + mvwprintz( w_vehicle, point_zero, COL_HEADER, _( "Scenario Vehicle:" ) ); + wprintz( w_vehicle, c_light_gray, ( "\n" ) ); + if( sorted_scens[cur_id]->vehicle() ) { + wprintz( w_vehicle, c_light_gray, sorted_scens[cur_id]->vehicle()->name ); + } + mvwprintz( w_flags, point_zero, COL_HEADER, _( "Scenario Flags:" ) ); wprintz( w_flags, c_light_gray, ( "\n" ) ); @@ -2153,6 +2168,7 @@ tab_direction set_scenario( avatar &u, points_left &points, wrefresh( w_sorting ); wrefresh( w_profession ); wrefresh( w_location ); + wrefresh( w_vehicle ); wrefresh( w_flags ); } ); @@ -2286,6 +2302,7 @@ tab_direction set_description( avatar &you, const bool allow_reroll, catacurses::window w_name; catacurses::window w_gender; catacurses::window w_location; + catacurses::window w_vehicle; catacurses::window w_stats; catacurses::window w_traits; catacurses::window w_scenario; @@ -2299,6 +2316,7 @@ tab_direction set_description( avatar &you, const bool allow_reroll, w_name = catacurses::newwin( 3, 42, point( 2, 5 ) ); w_gender = catacurses::newwin( 2, 33, point( 46, 5 ) ); w_location = catacurses::newwin( 2, 60, point( 100, 5 ) ); + w_vehicle = catacurses::newwin( 2, 60, point( 160, 5 ) ); w_stats = catacurses::newwin( 6, 20, point( 2, 9 ) ); w_traits = catacurses::newwin( TERMY - 10, 24, point( 22, 9 ) ); w_scenario = catacurses::newwin( 1, TERMX - 47, point( 46, 9 ) ); @@ -2525,6 +2543,17 @@ tab_direction set_description( avatar &you, const bool allow_reroll, you.start_location.obj().targets_count() ) ); wrefresh( w_location ); + werase( w_vehicle ); + mvwprintz( w_vehicle, point_zero, c_light_gray, _( "Starting Vehicle: " ) ); + const vproto_id scen_veh = g->scen->vehicle(); + const vproto_id prof_veh = you.prof->vehicle(); + if( scen_veh ) { + wprintz( w_vehicle, c_light_green, scen_veh->name ); + } else if( prof_veh ) { + wprintz( w_vehicle, c_light_green, prof_veh->name ); + } + wrefresh( w_vehicle ); + werase( w_scenario ); mvwprintz( w_scenario, point_zero, COL_HEADER, _( "Scenario: " ) ); wprintz( w_scenario, c_light_gray, g->scen->gender_appropriate_name( you.male ) ); @@ -2648,13 +2677,13 @@ tab_direction set_description( avatar &you, const bool allow_reroll, you.save_template( *name, points ); } } else if( action == "RANDOMIZE_CHAR_DESCRIPTION" ) { + you.male = one_in( 2 ); if( !MAP_SHARING::isSharing() ) { // Don't allow random names when sharing maps. We don't need to check at the top as you won't be able to edit the name you.pick_name(); no_name_entered = you.name.empty(); } you.set_base_age( rng( 16, 55 ) ); you.set_base_height( rng( 145, 200 ) ); - you.male = one_in( 2 ); } else if( action == "CHANGE_GENDER" ) { you.male = !you.male; } else if( action == "CHOOSE_LOCATION" ) { diff --git a/src/npc.cpp b/src/npc.cpp index 52bb270d6a6da..87cfee1178328 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1368,8 +1368,8 @@ float npc::vehicle_danger( int radius ) const int ax = wrapped_veh.v->global_pos3().x; int ay = wrapped_veh.v->global_pos3().y; - int bx = int( ax + cos( facing * M_PI / 180.0 ) * radius ); - int by = int( ay + sin( facing * M_PI / 180.0 ) * radius ); + int bx = int( ax + std::cos( facing * M_PI / 180.0 ) * radius ); + int by = int( ay + std::sin( facing * M_PI / 180.0 ) * radius ); // fake size /* This will almost certainly give the wrong size/location on customized diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index d569cf59ce41b..afd47b4806f95 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -342,7 +342,6 @@ void talk_function::goto_location( npc &p ) add_msg( m_info, _( "That is not a valid destination for %s." ), p.disp_name() ); return; } - p.set_companion_mission( p.global_omt_location(), "TRAVELER", "traveling", destination ); p.set_mission( NPC_MISSION_TRAVELLING ); p.chatbin.first_topic = "TALK_FRIEND_GUARD"; p.guard_pos = npc::no_goal_point; @@ -360,12 +359,6 @@ void talk_function::assign_guard( npc &p ) if( p.has_player_activity() ) { p.revert_after_activity(); } - - if( p.is_travelling() ) { - if( p.has_companion_mission() ) { - p.reset_companion_mission(); - } - } p.set_attitude( NPCATT_NULL ); p.set_mission( NPC_MISSION_GUARD_ALLY ); p.chatbin.first_topic = "TALK_FRIEND_GUARD"; @@ -395,12 +388,6 @@ void talk_function::assign_camp( npc &p ) if( p.has_player_activity() ) { p.revert_after_activity(); } - - if( p.is_travelling() ) { - if( p.has_companion_mission() ) { - p.reset_companion_mission(); - } - } p.chatbin.first_topic = "TALK_FRIEND_GUARD"; p.set_omt_destination(); } @@ -416,6 +403,9 @@ void talk_function::stop_guard( npc &p ) p.set_attitude( NPCATT_FOLLOW ); add_msg( _( "%s begins to follow you." ), p.name ); p.set_mission( NPC_MISSION_NULL ); + if( p.has_companion_mission() ) { + p.reset_companion_mission(); + } p.chatbin.first_topic = "TALK_FRIEND"; p.goal = npc::no_goal_point; p.guard_pos = npc::no_goal_point; diff --git a/src/overmap.cpp b/src/overmap.cpp index 47d23274abc5b..d806285d38681 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -2061,13 +2061,13 @@ void overmap::signal_hordes( const tripoint &p, const int sig_power ) const int targ_dist = rl_dist( p, mg.target ); // TODO: Base this on targ_dist:dist ratio. if( targ_dist < 5 ) { // If signal source already pursued by horde - mg.set_target( ( mg.target.x + p.x ) / 2, ( mg.target.y + p.y ) / 2 ); + mg.set_target( point( ( mg.target.x + p.x ) / 2, ( mg.target.y + p.y ) / 2 ) ); const int min_inc_inter = 3; // Min interest increase to already targeted source const int inc_roll = rng( min_inc_inter, calculated_inter ); mg.inc_interest( inc_roll ); add_msg( m_debug, "horde inc interest %d dist %d", inc_roll, dist ); } else { // New signal source - mg.set_target( p.x, p.y ); + mg.set_target( p.xy() ); mg.set_interest( min_capped_inter ); add_msg( m_debug, "horde set interest %d dist %d", min_capped_inter, dist ); } diff --git a/src/overmap_noise.cpp b/src/overmap_noise.cpp index 10ff4d9405333..fd4c7f976088c 100644 --- a/src/overmap_noise.cpp +++ b/src/overmap_noise.cpp @@ -11,10 +11,10 @@ float om_noise_layer_forest::noise_at( const point &local_omt_pos ) const { const point p = global_omt_pos( local_omt_pos ); float r = scaled_octave_noise_3d( 8, 0.5, 0.03, 0, 1, p.x, p.y, get_seed() ); - r = powf( r, 2 ); + r = std::pow( r, 2.0f ); float d = scaled_octave_noise_3d( 12, 0.5, 0.07, 0, 1, p.x, p.y, get_seed() ); - d = powf( d, 3 ); + d = std::pow( d, 3.0f ); return std::max( 0.0f, r - d * 0.5f ); } @@ -23,7 +23,7 @@ float om_noise_layer_floodplain::noise_at( const point &local_omt_pos ) const { const point p = global_omt_pos( local_omt_pos ); float r = scaled_octave_noise_3d( 8, 0.5, 0.05, 0, 1, p.x, p.y, get_seed() ); - r = powf( r, 2 ); + r = std::pow( r, 2.0f ); return r; } @@ -31,7 +31,7 @@ float om_noise_layer_lake::noise_at( const point &local_omt_pos ) const { const point p = global_omt_pos( local_omt_pos ); float r = scaled_octave_noise_3d( 16, 0.5, 0.002, 0, 1, p.x, p.y, get_seed() ); - r = powf( r, 4 ); + r = std::pow( r, 4.0f ); return r; } diff --git a/src/panels.cpp b/src/panels.cpp index c5a23387a2a48..bf455076ba0af 100644 --- a/src/panels.cpp +++ b/src/panels.cpp @@ -349,7 +349,7 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const double slope = ( cursx != targ.x ) ? static_cast( targ.y - cursy ) / static_cast ( targ.x - cursx ) : 4; - if( cursx == targ.x || fabs( slope ) > 3.5 ) { // Vertical slope + if( cursx == targ.x || std::fabs( slope ) > 3.5 ) { // Vertical slope if( targ.y > cursy ) { mvwputch( w_minimap, point( 3 + start_x, 6 + start_y ), c_red, '*' ); } else { @@ -358,7 +358,7 @@ void overmap_ui::draw_overmap_chunk( const catacurses::window &w_minimap, const } else { int arrowx = -1; int arrowy = -1; - if( fabs( slope ) >= 1. ) { // y diff is bigger! + if( std::fabs( slope ) >= 1. ) { // y diff is bigger! arrowy = ( targ.y > cursy ? 6 : 0 ); arrowx = static_cast( 3 + 3 * ( targ.y > cursy ? slope : ( 0 - slope ) ) ); if( arrowx < 0 ) { @@ -850,9 +850,9 @@ static int get_int_digits( const int &digits ) { int temp = std::abs( digits ); if( digits > 0 ) { - return static_cast( log10( static_cast( temp ) ) ) + 1; + return static_cast( std::log10( static_cast( temp ) ) ) + 1; } else if( digits < 0 ) { - return static_cast( log10( static_cast( temp ) ) ) + 2; + return static_cast( std::log10( static_cast( temp ) ) ) + 2; } return 1; } @@ -2249,9 +2249,8 @@ void panel_manager::deserialize( JsonIn &jsin ) jsin.end_array(); } -void panel_manager::draw_adm( const catacurses::window &w, size_t column, size_t index ) +void panel_manager::show_adm() { - input_context ctxt( "PANEL_MGMT" ); ctxt.register_action( "HELP_KEYBINDINGS" ); ctxt.register_action( "QUIT" ); @@ -2262,184 +2261,168 @@ void panel_manager::draw_adm( const catacurses::window &w, size_t column, size_t ctxt.register_action( "MOVE_PANEL" ); ctxt.register_action( "TOGGLE_PANEL" ); - // FIXME: temporarily disable redrawing of lower UIs before this UI is migrated to `ui_adaptor` - ui_adaptor ui( ui_adaptor::disable_uis_below {} ); - const std::vector column_widths = { 17, 37, 17 }; - size_t max_index = 0; - int counter = 0; - bool selected = false; + + size_t current_col = 0; + size_t current_row = 0; + bool swapping = false; + size_t source_row = 0; size_t source_index = 0; - size_t target_index = 0; - bool redraw = true; + bool recalc = true; bool exit = false; // map of row the panel is on vs index // panels not renderable due to game configuration will not be in this map std::map row_indices; - while( !exit ) { + + g->show_panel_adm = true; + g->invalidate_main_ui_adaptor(); + + catacurses::window w; + + ui_adaptor ui; + ui.on_screen_resize( [&]( ui_adaptor & ui ) { + w = catacurses::newwin( 20, 75, + point( ( TERMX / 2 ) - 38, ( TERMY / 2 ) - 10 ) ); + + ui.position_from_window( w ); + } ); + ui.mark_resize(); + + ui.on_redraw( [&]( const ui_adaptor & ) { auto &panels = layouts[current_layout_id]; - if( redraw ) { - redraw = false; - werase( w ); - decorate_panel( _( "SIDEBAR OPTIONS" ), w ); - // clear the panel list - for( int i = 1; i <= 18; i++ ) { - for( int j = 1; j <= column_widths[0]; j++ ) { - mvwputch( w, point( j, i ), c_black, ' ' ); + werase( w ); + decorate_panel( _( "SIDEBAR OPTIONS" ), w ); + + for( std::pair row_indx : row_indices ) { + std::string name = _( panels[row_indx.second].get_name() ); + if( swapping && source_index == row_indx.second ) { + mvwprintz( w, point( 5, current_row + 1 ), c_yellow, name ); + } else { + int offset = 0; + if( !swapping ) { + offset = 0; + } else if( current_row > source_row && row_indx.first > source_row && + row_indx.first <= current_row ) { + offset = -1; + } else if( current_row < source_row && row_indx.first < source_row && + row_indx.first >= current_row ) { + offset = 1; } + const nc_color toggle_color = panels[row_indx.second].toggle ? c_white : c_dark_gray; + mvwprintz( w, point( 4, row_indx.first + 1 + offset ), toggle_color, name ); } - // the row that the panel name is printed on - int row = 1; + } + size_t i = 1; + for( const auto &layout : layouts ) { + mvwprintz( w, point( column_widths[0] + column_widths[1] + 4, i ), + current_layout_id == layout.first ? c_light_blue : c_white, _( layout.first ) ); + i++; + } + int col_offset = 0; + for( i = 0; i < current_col; i++ ) { + col_offset += column_widths[i]; + } + mvwprintz( w, point( 1 + ( col_offset ), current_row + 1 ), c_yellow, ">>" ); + mvwvline( w, point( column_widths[0], 1 ), 0, 18 ); + mvwvline( w, point( column_widths[0] + column_widths[1], 1 ), 0, 18 ); + + col_offset = column_widths[0] + 2; + int col_width = column_widths[1] - 4; + mvwprintz( w, point( col_offset, 1 ), c_light_green, trunc_ellipse( ctxt.get_desc( "TOGGLE_PANEL" ), + col_width ) + ":" ); + mvwprintz( w, point( col_offset, 2 ), c_white, _( "Toggle panels on/off" ) ); + mvwprintz( w, point( col_offset, 3 ), c_light_green, trunc_ellipse( ctxt.get_desc( "MOVE_PANEL" ), + col_width ) + ":" ); + mvwprintz( w, point( col_offset, 4 ), c_white, _( "Change display order" ) ); + mvwprintz( w, point( col_offset, 5 ), c_light_green, trunc_ellipse( ctxt.get_desc( "QUIT" ), + col_width ) + ":" ); + mvwprintz( w, point( col_offset, 6 ), c_white, _( "Exit" ) ); + + wrefresh( w ); + } ); + + while( !exit ) { + auto &panels = layouts[current_layout_id]; + + if( recalc ) { + recalc = false; + row_indices.clear(); - for( size_t i = 0; i < panels.size(); i++ ) { + for( size_t i = 0, row = 0; i < panels.size(); i++ ) { if( panels[i].render() ) { - row_indices.emplace( row - 1, i ); + row_indices.emplace( row, i ); row++; - } else if( !panels[i].render && column == 0 ) { - if( selected && index == i ) { - row++; - } } } + } - max_index = column == 0 ? row_indices.size() : layouts.size(); - int vertical_offset = 0; - int selected_offset = 0; - size_t modified_index = row_indices[index - 1]; + const size_t num_rows = current_col == 0 ? row_indices.size() : layouts.size(); + current_row = clamp( current_row, 0, num_rows - 1 ); - for( std::pair row_indx : row_indices ) { - nc_color toggle_color = panels[row_indx.second].toggle ? c_white : c_dark_gray; - std::string name = _( panels[row_indx.second].get_name() ); - if( !selected ) { - mvwprintz( w, point( 4, row_indx.first + 1 ), toggle_color, name ); - } else { - if( modified_index < row_indx.second ) { - vertical_offset = 2; - } else if( modified_index == row_indx.second && row_indx.second < source_index ) { - vertical_offset = 2; - } else { - vertical_offset = 1; - } - mvwprintz( w, point( 4, row_indx.first + vertical_offset ), toggle_color, name ); - if( source_index == row_indx.second ) { - if( modified_index < source_index ) { - selected_offset = 0; - } else { - selected_offset = 1; - } - mvwprintz( w, point( 5, index + selected_offset ), c_yellow, name ); - } - } - } - size_t i = 1; - for( const auto &layout : layouts ) { - mvwprintz( w, point( column_widths[0] + column_widths[1] + 4, i ), - current_layout_id == layout.first ? c_light_blue : c_white, _( layout.first ) ); - i++; - } - int col_offset = 0; - for( i = 0; i < column; i++ ) { - col_offset += column_widths[i]; - } - mvwprintz( w, point( 1 + ( col_offset ), index + selected_offset ), c_yellow, ">>" ); - mvwvline( w, point( column_widths[0], 1 ), 0, 18 ); - mvwvline( w, point( column_widths[0] + column_widths[1], 1 ), 0, 18 ); - - col_offset = column_widths[0] + 2; - int col_width = column_widths[1] - 4; - mvwprintz( w, point( col_offset, 1 ), c_light_green, trunc_ellipse( ctxt.get_desc( "TOGGLE_PANEL" ), - col_width ) + ":" ); - mvwprintz( w, point( col_offset, 2 ), c_white, _( "Toggle panels on/off" ) ); - mvwprintz( w, point( col_offset, 3 ), c_light_green, trunc_ellipse( ctxt.get_desc( "MOVE_PANEL" ), - col_width ) + ":" ); - mvwprintz( w, point( col_offset, 4 ), c_white, _( "Change display order" ) ); - mvwprintz( w, point( col_offset, 5 ), c_light_green, trunc_ellipse( ctxt.get_desc( "QUIT" ), - col_width ) + ":" ); - mvwprintz( w, point( col_offset, 6 ), c_white, _( "Exit" ) ); - } - wrefresh( w ); + ui_manager::redraw(); const std::string action = ctxt.handle_input(); if( action == "UP" ) { - if( index > 1 ) { - index -= 1; - } else if( index == 1 ) { - index = max_index; + if( current_row > 0 ) { + current_row -= 1; + } else { + current_row = num_rows - 1; } - redraw = true; } else if( action == "DOWN" ) { - if( index < max_index ) { - index += 1; - } else if( index == max_index ) { - index = 1; + if( current_row + 1 < num_rows ) { + current_row += 1; + } else { + current_row = 0; } - redraw = true; - } else if( action == "MOVE_PANEL" && column == 0 ) { - counter += 1; - // source window from the swap - if( counter == 1 ) { + } else if( action == "MOVE_PANEL" && current_col == 0 ) { + swapping = !swapping; + if( swapping ) { + // source window from the swap // saving win1 index - source_index = row_indices[index - 1]; - selected = true; - } - // dest window for the swap - if( counter == 2 ) { + source_row = current_row; + source_index = row_indices[current_row]; + } else { + // dest window for the swap // saving win2 index - target_index = row_indices[index - 1]; + const size_t target_index = row_indices[current_row]; int distance = target_index - source_index; size_t step_dir = distance > 0 ? 1 : -1; for( size_t i = source_index; i != target_index; i += step_dir ) { std::swap( panels[i], panels[i + step_dir] ); } - werase( w ); - wrefresh( g->w_terrain ); - g->draw_panels( column, index, true ); - return; - } - redraw = true; - } else if( action == "MOVE_PANEL" && column == 2 ) { - auto iter = layouts.begin(); - for( size_t i = 1; i < index; i++ ) { - iter++; + g->invalidate_main_ui_adaptor(); + recalc = true; } + } else if( !swapping && action == "MOVE_PANEL" && current_col == 2 ) { + auto iter = std::next( layouts.begin(), current_row ); current_layout_id = iter->first; int width = panel_manager::get_manager().get_current_layout().begin()->get_width(); update_offsets( width ); int h; // to_map_font_dimension needs a second input to_map_font_dimension( width, h ); - werase( w ); - wrefresh( g->w_terrain ); - g->draw_panels( column, index, true ); // tell the game that the main screen might have a different size now. - g->init_ui( true ); - return; - } else if( action == "RIGHT" || action == "LEFT" ) { + g->init_ui( false ); + g->invalidate_main_ui_adaptor(); + recalc = true; + } else if( !swapping && ( action == "RIGHT" || action == "LEFT" ) ) { // there are only two columns - if( column == 0 ) { - column = 2; - if( index > layouts.size() ) { - index = layouts.size(); - } + if( current_col == 0 ) { + current_col = 2; } else { - column = 0; - if( index > get_current_layout().size() ) { - index = get_current_layout().size(); - } + current_col = 0; } - redraw = true; - } - if( action == "TOGGLE_PANEL" && column == 0 ) { - panels[row_indices[index - 1]].toggle = !panels[row_indices[index - 1]].toggle; - wrefresh( g->w_terrain ); - g->draw_panels( column, index, true ); - return; + } else if( !swapping && action == "TOGGLE_PANEL" && current_col == 0 ) { + panels[row_indices[current_row]].toggle = !panels[row_indices[current_row]].toggle; + g->invalidate_main_ui_adaptor(); } else if( action == "QUIT" ) { exit = true; - g->show_panel_adm = false; save(); } } + + g->show_panel_adm = false; + g->invalidate_main_ui_adaptor(); } diff --git a/src/panels.h b/src/panels.h index 3e77b25b06409..45c9b06cf0ebf 100644 --- a/src/panels.h +++ b/src/panels.h @@ -79,7 +79,7 @@ class panel_manager int get_width_right(); int get_width_left(); - void draw_adm( const catacurses::window &w, size_t column = 0, size_t index = 1 ); + void show_adm(); void init(); diff --git a/src/player.cpp b/src/player.cpp index 091497829d0cf..2adfed4d36394 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -281,7 +281,6 @@ player::player() sight_max = 9999; last_batch = 0; lastconsumed = itype_id( "null" ); - next_expected_position = cata::nullopt; death_drops = true; nv_cached = false; @@ -473,7 +472,6 @@ int player::kcal_speed_penalty() } }; if( get_kcal_percent() > 0.95f ) { - // TODO: get speed penalties for being too fat, too return 0; } else { return std::round( multi_lerp( starv_thresholds, get_bmi() ) ); @@ -508,7 +506,7 @@ void player::recalc_speed_bonus() if( get_thirst() > 40 ) { mod_speed_bonus( thirst_speed_penalty( get_thirst() ) ); } - // fat or underweight, you get slower. cumulative with hunger + // when underweight, you get slower. cumulative with hunger mod_speed_bonus( kcal_speed_penalty() ); for( const auto &maps : *effects ) { @@ -4411,254 +4409,6 @@ void player::environmental_revert_effect() reset_encumbrance(); } -void player::set_destination( const std::vector &route, - const player_activity &new_destination_activity ) -{ - auto_move_route = route; - set_destination_activity( new_destination_activity ); - destination_point.emplace( g->m.getabs( route.back() ) ); -} - -void player::clear_destination() -{ - auto_move_route.clear(); - clear_destination_activity(); - destination_point = cata::nullopt; - next_expected_position = cata::nullopt; -} - -bool player::has_distant_destination() const -{ - return has_destination() && !get_destination_activity().is_null() && - get_destination_activity().id() == "ACT_TRAVELLING" && !omt_path.empty(); -} - -bool player::is_auto_moving() const -{ - return destination_point.has_value(); -} - -bool player::has_destination() const -{ - return !auto_move_route.empty(); -} - -bool player::has_destination_activity() const -{ - return !get_destination_activity().is_null() && destination_point && - position == g->m.getlocal( *destination_point ); -} - -void player::start_destination_activity() -{ - if( !has_destination_activity() ) { - debugmsg( "Tried to start invalid destination activity" ); - return; - } - - assign_activity( get_destination_activity() ); - clear_destination(); -} - -std::vector &player::get_auto_move_route() -{ - return auto_move_route; -} - -action_id player::get_next_auto_move_direction() -{ - if( !has_destination() ) { - return ACTION_NULL; - } - - if( next_expected_position ) { - if( pos() != *next_expected_position ) { - // We're off course, possibly stumbling or stuck, cancel auto move - return ACTION_NULL; - } - } - - next_expected_position.emplace( auto_move_route.front() ); - auto_move_route.erase( auto_move_route.begin() ); - - tripoint dp = *next_expected_position - pos(); - - // Make sure the direction is just one step and that - // all diagonal moves have 0 z component - if( std::abs( dp.x ) > 1 || std::abs( dp.y ) > 1 || std::abs( dp.z ) > 1 || - ( std::abs( dp.z ) != 0 && ( std::abs( dp.x ) != 0 || std::abs( dp.y ) != 0 ) ) ) { - // Should never happen, but check just in case - return ACTION_NULL; - } - return get_movement_action_from_delta( dp, iso_rotate::yes ); -} - -bool player::defer_move( const tripoint &next ) -{ - // next must be adjacent to current pos - if( square_dist( next, pos() ) != 1 ) { - return false; - } - // next must be adjacent to subsequent move in any preexisting automove route - if( has_destination() && square_dist( auto_move_route.front(), next ) != 1 ) { - return false; - } - auto_move_route.insert( auto_move_route.begin(), next ); - next_expected_position = pos(); - return true; -} - -void player::shift_destination( const point &shift ) -{ - if( next_expected_position ) { - *next_expected_position += shift; - } - - for( auto &elem : auto_move_route ) { - elem += shift; - } -} - -bool player::has_weapon() const -{ - return !unarmed_attack(); -} - -int player::get_hp() const -{ - return get_hp( num_hp_parts ); -} - -int player::get_hp( hp_part bp ) const -{ - if( bp < num_hp_parts ) { - return hp_cur[bp]; - } - int hp_total = 0; - for( int i = 0; i < num_hp_parts; ++i ) { - hp_total += hp_cur[i]; - } - return hp_total; -} - -int player::get_hp_max() const -{ - return get_hp_max( num_hp_parts ); -} - -int player::get_hp_max( hp_part bp ) const -{ - if( bp < num_hp_parts ) { - return hp_max[bp]; - } - int hp_total = 0; - for( int i = 0; i < num_hp_parts; ++i ) { - hp_total += hp_max[i]; - } - return hp_total; -} - -Creature::Attitude player::attitude_to( const Creature &other ) const -{ - const auto m = dynamic_cast( &other ); - if( m != nullptr ) { - if( m->friendly != 0 ) { - return A_FRIENDLY; - } - switch( m->attitude( const_cast( this ) ) ) { - // player probably does not want to harm them, but doesn't care much at all. - case MATT_FOLLOW: - case MATT_FPASSIVE: - case MATT_IGNORE: - case MATT_FLEE: - return A_NEUTRAL; - // player does not want to harm those. - case MATT_FRIEND: - case MATT_ZLAVE: - // Don't want to harm your zlave! - return A_FRIENDLY; - case MATT_ATTACK: - return A_HOSTILE; - case MATT_NULL: - case NUM_MONSTER_ATTITUDES: - break; - } - - return A_NEUTRAL; - } - - const auto p = dynamic_cast( &other ); - if( p != nullptr ) { - if( p->is_enemy() ) { - return A_HOSTILE; - } else if( p->is_player_ally() ) { - return A_FRIENDLY; - } else { - return A_NEUTRAL; - } - } else if( &other == this ) { - return A_FRIENDLY; - } - - return A_NEUTRAL; -} - -bool player::sees( const tripoint &t, bool, int ) const -{ - static const bionic_id str_bio_night( "bio_night" ); - const int wanted_range = rl_dist( pos(), t ); - bool can_see = is_player() ? g->m.pl_sees( t, wanted_range ) : - Creature::sees( t ); - // Clairvoyance is now pretty cheap, so we can check it early - if( wanted_range < MAX_CLAIRVOYANCE && wanted_range < clairvoyance() ) { - return true; - } - // Only check if we need to override if we already came to the opposite conclusion. - if( can_see && wanted_range < 15 && wanted_range > sight_range( 1 ) && - has_active_bionic( str_bio_night ) ) { - can_see = false; - } - if( can_see && wanted_range > unimpaired_range() ) { - can_see = false; - } - - return can_see; -} - -bool player::sees( const Creature &critter ) const -{ - // This handles only the player/npc specific stuff (monsters don't have traits or bionics). - const int dist = rl_dist( pos(), critter.pos() ); - if( dist <= 3 && has_active_mutation( trait_ANTENNAE ) ) { - return true; - } - - return Creature::sees( critter ); -} - -nc_color player::bodytemp_color( int bp ) const -{ - nc_color color = c_light_gray; // default - if( bp == bp_eyes ) { - color = c_light_gray; // Eyes don't count towards warmth - } else if( temp_conv[bp] > BODYTEMP_SCORCHING ) { - color = c_red; - } else if( temp_conv[bp] > BODYTEMP_VERY_HOT ) { - color = c_light_red; - } else if( temp_conv[bp] > BODYTEMP_HOT ) { - color = c_yellow; - } else if( temp_conv[bp] > BODYTEMP_COLD ) { - color = c_green; - } else if( temp_conv[bp] > BODYTEMP_VERY_COLD ) { - color = c_light_blue; - } else if( temp_conv[bp] > BODYTEMP_FREEZING ) { - color = c_cyan; - } else if( temp_conv[bp] <= BODYTEMP_FREEZING ) { - color = c_blue; - } - return color; -} - //message related stuff void player::add_msg_if_player( const std::string &msg ) const { @@ -4696,100 +4446,6 @@ void player::add_msg_player_or_say( const game_message_params ¶ms, Messages::add_msg( params, player_msg ); } -bool player::knows_trap( const tripoint &pos ) const -{ - const tripoint p = g->m.getabs( pos ); - return known_traps.count( p ) > 0; -} - -void player::add_known_trap( const tripoint &pos, const trap &t ) -{ - const tripoint p = g->m.getabs( pos ); - if( t.is_null() ) { - known_traps.erase( p ); - } else { - // TODO: known_traps should map to a trap_str_id - known_traps[p] = t.id.str(); - } -} - -bool player::can_hear( const tripoint &source, const int volume ) const -{ - if( is_deaf() ) { - return false; - } - - // source is in-ear and at our square, we can hear it - if( source == pos() && volume == 0 ) { - return true; - } - const int dist = rl_dist( source, pos() ); - const float volume_multiplier = hearing_ability(); - return ( volume - weather::sound_attn( g->weather.weather ) ) * volume_multiplier >= dist; -} - -float player::hearing_ability() const -{ - float volume_multiplier = 1.0; - - // Mutation/Bionic volume modifiers - if( has_active_bionic( bio_ears ) && !has_active_bionic( bio_earplugs ) ) { - volume_multiplier *= 3.5; - } - if( has_trait( trait_PER_SLIME ) ) { - // Random hearing :-/ - // (when it's working at all, see player.cpp) - // changed from 0.5 to fix Mac compiling error - volume_multiplier *= ( rng( 1, 2 ) ); - } - - volume_multiplier *= Character::mutation_value( "hearing_modifier" ); - - if( has_effect( effect_deaf ) ) { - // Scale linearly up to 30 minutes - volume_multiplier *= ( 30_minutes - get_effect_dur( effect_deaf ) ) / 30_minutes; - } - - if( has_effect( effect_earphones ) ) { - volume_multiplier *= .25; - } - - return volume_multiplier; -} - -std::vector player::short_description_parts() const -{ - std::vector result; - - if( is_armed() ) { - result.push_back( _( "Wielding: " ) + weapon.tname() ); - } - const std::string worn_str = enumerate_as_string( worn.begin(), worn.end(), - []( const item & it ) { - return it.tname(); - } ); - if( !worn_str.empty() ) { - result.push_back( _( "Wearing: " ) + worn_str ); - } - const int visibility_cap = 0; // no cap - const auto trait_str = visible_mutations( visibility_cap ); - if( !trait_str.empty() ) { - result.push_back( _( "Traits: " ) + trait_str ); - } - return result; -} - -std::string player::short_description() const -{ - return join( short_description_parts(), "; " ); -} - -int player::print_info( const catacurses::window &w, int vStart, int, int column ) const -{ - mvwprintw( w, point( column, vStart++ ), _( "You (%s)" ), name ); - return vStart; -} - bool player::query_yn( const std::string &mes ) const { return ::query_yn( mes ); diff --git a/src/player.h b/src/player.h index 86e265d05b129..af8efba19cf8a 100644 --- a/src/player.h +++ b/src/player.h @@ -143,10 +143,6 @@ class player : public Character /** Returns what color the player should be drawn as */ nc_color basic_symbol_color() const override; - std::vector short_description_parts() const; - std::string short_description() const; - int print_info( const catacurses::window &w, int vStart, int vLines, int column ) const override; - // populate variables, inventory items, and misc from json object virtual void deserialize( JsonIn &jsin ) = 0; @@ -166,9 +162,6 @@ class player : public Character /** Calculates the various speed bonuses we will get from mutations, etc. */ void recalc_speed_bonus(); - /** Define color for displaying the body temperature */ - nc_color bodytemp_color( int bp ) const; - /** Maintains body wetness and handles the rate at which the player dries */ void update_body_wetness( const w_point &weather ); @@ -199,13 +192,6 @@ class player : public Character /** Called when a player triggers a trap, returns true if they don't set it off */ bool avoid_trap( const tripoint &pos, const trap &tr ) const override; - // see Creature::sees - bool sees( const tripoint &t, bool is_player = false, int range_mod = 0 ) const override; - // see Creature::sees - bool sees( const Creature &critter ) const override; - - Attitude attitude_to( const Creature &other ) const override; - void pause(); // '.' command; pauses & resets recoil // martialarts.cpp @@ -579,8 +565,6 @@ class player : public Character bool has_gun_for_ammo( const ammotype &at ) const; bool has_magazine_for_ammo( const ammotype &at ) const; - bool has_weapon() const override; - // Checks crafting inventory for books providing the requested recipe. // Then checks nearby NPCs who could provide it too. // Returns -1 to indicate recipe not found, otherwise difficulty to learn. @@ -721,33 +705,12 @@ class player : public Character void consume_tools( const std::vector &tools, int batch = 1, const std::string &hotkeys = DEFAULT_HOTKEYS ); - // Auto move methods - void set_destination( const std::vector &route, - const player_activity &new_destination_activity = player_activity() ); - void clear_destination(); - bool has_distant_destination() const; - - // true if the player is auto moving, or if the player is going to finish - // auto moving but the destination is not yet reset, such as in avatar_action::move - bool is_auto_moving() const; - // true if there are further moves in the auto move route - bool has_destination() const; - // true if player has destination activity AND is standing on destination tile - bool has_destination_activity() const; - // starts destination activity and cleans up to ensure it is called only once - void start_destination_activity(); - std::vector &get_auto_move_route(); - action_id get_next_auto_move_direction(); - bool defer_move( const tripoint &next ); - void shift_destination( const point &shift ); - // ---------------VALUES----------------- tripoint view_offset; // Is currently in control of a vehicle bool controlling_vehicle; // Relative direction of a grab, add to posx, posy to get the coordinates of the grabbed thing. tripoint grab_point; - cata::optional destination_point; int volume; const profession *prof; @@ -781,16 +744,6 @@ class player : public Character bool is_hallucination() const override; void environmental_revert_effect(); - // Checks whether a player can hear a sound at a given volume and location. - bool can_hear( const tripoint &source, int volume ) const; - // Returns a multiplier indicating the keenness of a player's hearing. - float hearing_ability() const; - - int get_hp( hp_part bp ) const override; - int get_hp() const override; - int get_hp_max( hp_part bp ) const override; - int get_hp_max() const override; - //message related stuff using Character::add_msg_if_player; void add_msg_if_player( const std::string &msg ) const override; @@ -806,9 +759,6 @@ class player : public Character void add_msg_player_or_say( const game_message_params ¶ms, const std::string &player_msg, const std::string &npc_speech ) const override; - using trap_map = std::map; - bool knows_trap( const tripoint &pos ) const; - void add_known_trap( const tripoint &pos, const trap &t ); /** Search surrounding squares for traps (and maybe other things in the future). */ void search_surroundings(); // formats and prints encumbrance info to specified window @@ -830,8 +780,6 @@ class player : public Character protected: - trap_map known_traps; - void store( JsonOut &json ) const; void load( const JsonObject &data ); @@ -849,9 +797,6 @@ class player : public Character private: - std::vector auto_move_route; - // Used to make sure auto move is canceled if we stumble off course - cata::optional next_expected_position; /** warnings from a faction about bad behavior */ std::map> warning_record; diff --git a/src/player_display.cpp b/src/player_display.cpp index 057d3a411df5f..f5533d987ed75 100644 --- a/src/player_display.cpp +++ b/src/player_display.cpp @@ -300,7 +300,7 @@ static void draw_stats_tab( const catacurses::window &w_stats, const catacurses: string_format( _( "Melee to-hit bonus: %+.1lf" ), you.get_melee_hit_base() ) ); print_colored_text( w_info, point( 1, 4 ), col_temp, c_light_gray, string_format( _( "Ranged penalty: %+d" ), - -abs( you.ranged_dex_mod() ) ) ); + -std::abs( you.ranged_dex_mod() ) ) ); print_colored_text( w_info, point( 1, 5 ), col_temp, c_light_gray, string_format( _( "Throwing penalty per target's dodge: %+d" ), you.throw_dispersion_per_dodge( false ) ) ); diff --git a/src/ranged.cpp b/src/ranged.cpp index a3ca204437490..9008e6cb2aadf 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -1468,9 +1468,9 @@ std::vector target_handler::target_ui( player &pc, target_mode mode, } static const double recoil_per_deg = MAX_RECOIL / 180; - const double phi = fmod( std::abs( coord_to_angle( pc.pos(), dst ) - - coord_to_angle( pc.pos(), recoil_pos ) ), - 360.0 ); + const double phi = std::fmod( std::abs( coord_to_angle( pc.pos(), dst ) - + coord_to_angle( pc.pos(), recoil_pos ) ), + 360.0 ); const double angle = phi > 180.0 ? 360.0 - phi : phi; return std::min( recoil_pc + angle * recoil_per_deg, MAX_RECOIL ); diff --git a/src/rect_range.h b/src/rect_range.h index bb93a38f598e0..a6ba897c1b645 100644 --- a/src/rect_range.h +++ b/src/rect_range.h @@ -2,6 +2,8 @@ #ifndef CATA_SRC_RECT_RANGE_H #define CATA_SRC_RECT_RANGE_H +#include "point.h" + // This is a template parameter, it's usually SDL_Rect, but that way the class // can be used without include any SDL header. template @@ -10,12 +12,11 @@ class rect_range private: int width; int height; - int xcount; - int ycount; + point count; public: - rect_range( const int w, const int h, const int xc, const int yc ) : width( w ), height( h ), - xcount( xc ), ycount( yc ) { + rect_range( const int w, const int h, const point &c ) : width( w ), height( h ), + count( c ) { } class iterator @@ -36,7 +37,7 @@ class rect_range return !operator==( rhs ); } RectType operator*() const { - return { ( index % range->xcount ) *range->width, ( index / range->xcount ) *range->height, range->width, range->height }; + return { ( index % range->count.x ) *range->width, ( index / range->count.x ) *range->height, range->width, range->height }; } iterator operator+( const int offset ) const { @@ -55,7 +56,7 @@ class rect_range return iterator( this, 0 ); } iterator end() const { - return iterator( this, xcount * ycount ); + return iterator( this, count.x * count.y ); } }; diff --git a/src/savegame.cpp b/src/savegame.cpp index 627187868bd1c..6a02e55e10c6f 100644 --- a/src/savegame.cpp +++ b/src/savegame.cpp @@ -80,6 +80,7 @@ void game::serialize( std::ostream &fout ) // basic game state information. json.member( "turn", calendar::turn ); json.member( "calendar_start", calendar::start_of_cataclysm ); + json.member( "game_start", calendar::start_of_game ); json.member( "initial_season", static_cast( calendar::initial_season ) ); json.member( "auto_travel_mode", auto_travel_mode ); json.member( "run_mode", static_cast( safe_mode ) ); @@ -194,6 +195,10 @@ void game::unserialize( std::istream &fin ) calendar::turn = tmpturn; calendar::start_of_cataclysm = tmpcalstart; + if( !data.read( "game_start", calendar::start_of_game ) ) { + calendar::start_of_game = calendar::start_of_cataclysm; + } + load_map( tripoint( levx + comx * OMAPX * 2, levy + comy * OMAPY * 2, levz ) ); safe_mode = static_cast( tmprun ); diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 89bbab3b3f7ea..6405aee1e848c 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -625,6 +625,14 @@ void Character::load( const JsonObject &data ) } data.read( "stomach", stomach ); data.read( "guts", guts ); + data.read( "automoveroute", auto_move_route ); + + known_traps.clear(); + for( JsonObject pmap : data.get_array( "known_traps" ) ) { + const tripoint p( pmap.get_int( "x" ), pmap.get_int( "y" ), pmap.get_int( "z" ) ); + const std::string t = pmap.get_string( "trap" ); + known_traps.insert( trap_map::value_type( p, t ) ); + } } /** @@ -751,6 +759,18 @@ void Character::store( JsonOut &json ) const } json.member( "stomach", stomach ); json.member( "guts", guts ); + json.member( "automoveroute", auto_move_route ); + json.member( "known_traps" ); + json.start_array(); + for( const auto &elem : known_traps ) { + json.start_object(); + json.member( "x", elem.first.x ); + json.member( "y", elem.first.y ); + json.member( "z", elem.first.z ); + json.member( "trap", elem.second ); + json.end_object(); + } + json.end_array(); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -788,19 +808,6 @@ void player::store( JsonOut &json ) const // "Looks like I picked the wrong week to quit smoking." - Steve McCroskey json.member( "addictions", addictions ); json.member( "followers", follower_ids ); - json.member( "known_traps" ); - json.start_array(); - for( const auto &elem : known_traps ) { - json.start_object(); - json.member( "x", elem.first.x ); - json.member( "y", elem.first.y ); - json.member( "z", elem.first.z ); - json.member( "trap", elem.second ); - json.end_object(); - } - json.end_array(); - - json.member( "automoveroute", auto_move_route ); json.member( "worn", worn ); // also saves contents json.member( "inv" ); @@ -877,14 +884,6 @@ void player::load( const JsonObject &data ) data.read( "addictions", addictions ); data.read( "followers", follower_ids ); - known_traps.clear(); - for( JsonObject pmap : data.get_array( "known_traps" ) ) { - const tripoint p( pmap.get_int( "x" ), pmap.get_int( "y" ), pmap.get_int( "z" ) ); - const std::string t = pmap.get_string( "trap" ); - known_traps.insert( trap_map::value_type( p, t ) ); - } - - data.read( "automoveroute", auto_move_route ); // Add the earplugs. if( has_bionic( bionic_id( "bio_ears" ) ) && !has_bionic( bionic_id( "bio_earplugs" ) ) ) { diff --git a/src/scenario.cpp b/src/scenario.cpp index 33a3d61dd2e59..45385f768a2e7 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -90,6 +90,10 @@ void scenario::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "flags", flags, auto_flags_reader<> {} ); optional( jo, was_loaded, "map_extra", _map_extra, "mx_null" ); optional( jo, was_loaded, "missions", _missions, auto_flags_reader {} ); + + if( jo.has_string( "vehicle" ) ) { + _starting_vehicle = vproto_id( jo.get_string( "vehicle" ) ); + } } const scenario *scenario::generic() @@ -186,6 +190,11 @@ void scenario::check_definition() const m.c_str(), id.c_str() ); } } + + if( _starting_vehicle && !_starting_vehicle.is_valid() ) { + debugmsg( "vehicle prototype %s for profession %s does not exist", _starting_vehicle.c_str(), + id.c_str() ); + } } const string_id &scenario::ident() const @@ -401,6 +410,11 @@ int scenario::start_location_targets_count() const return cnt; } +vproto_id scenario::vehicle() const +{ + return _starting_vehicle; +} + bool scenario::traitquery( const trait_id &trait ) const { return _allowed_traits.count( trait ) != 0 || is_locked_trait( trait ) || diff --git a/src/scenario.h b/src/scenario.h index 6abeaa95ce939..5319982710ab0 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -50,6 +50,8 @@ class scenario std::string _map_extra; std::vector _missions; + vproto_id _starting_vehicle = vproto_id::NULL_ID(); + void load( const JsonObject &jo, const std::string &src ); bool scenario_traits_conflict_with_profession_traits( const profession &p ) const; @@ -80,6 +82,8 @@ class scenario int start_location_count() const; int start_location_targets_count() const; + vproto_id vehicle() const; + const profession *weighted_random_profession() const; std::vector> permitted_professions() const; diff --git a/src/scent_map.cpp b/src/scent_map.cpp index b5ced666da00c..7b65a238d92e7 100644 --- a/src/scent_map.cpp +++ b/src/scent_map.cpp @@ -79,12 +79,12 @@ void scent_map::draw( const catacurses::window &win, const int div, const tripoi } } -void scent_map::shift( const int sm_shift_x, const int sm_shift_y ) +void scent_map::shift( const point &sm_shift ) { scent_array new_scent; for( size_t x = 0; x < MAPSIZE_X; ++x ) { for( size_t y = 0; y < MAPSIZE_Y; ++y ) { - const point p( x + sm_shift_x, y + sm_shift_y ); + const point p = point( x, y ) + sm_shift; new_scent[x][y] = inbounds( p ) ? grscent[ p.x ][ p.y ] : 0; } } diff --git a/src/scent_map.h b/src/scent_map.h index 55209d65201e5..10f7058c79e52 100644 --- a/src/scent_map.h +++ b/src/scent_map.h @@ -63,7 +63,7 @@ class scent_map void update( const tripoint ¢er, map &m ); void reset(); void decay(); - void shift( int sm_shift_x, int sm_shift_y ); + void shift( const point &sm_shift ); /** * Get the scent value at the given position. diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp index 34d467094207c..59728e06b2a3f 100644 --- a/src/sdltiles.cpp +++ b/src/sdltiles.cpp @@ -2383,7 +2383,7 @@ void update_finger_repeat_delay() { float delta_x = finger_curr_x - finger_down_x; float delta_y = finger_curr_y - finger_down_y; - float dist = ( float )sqrtf( delta_x * delta_x + delta_y * delta_y ); + float dist = std::sqrt( delta_x * delta_x + delta_y * delta_y ); float longest_window_edge = std::max( WindowWidth, WindowHeight ); float t = clmp( ( dist - ( get_option( "ANDROID_DEADZONE_RANGE" ) * longest_window_edge ) ) / std::max( 0.01f, ( get_option( "ANDROID_REPEAT_DELAY_RANGE" ) ) * longest_window_edge ), @@ -2420,7 +2420,7 @@ void handle_finger_input( uint32_t ticks ) float delta_x = finger_curr_x - finger_down_x; float delta_y = finger_curr_y - finger_down_y; - float dist = ( float )sqrtf( delta_x * delta_x + delta_y * delta_y ); // in pixel space + float dist = std::sqrt( delta_x * delta_x + delta_y * delta_y ); // in pixel space bool handle_diagonals = touch_input_context.is_action_registered( "LEFTUP" ); bool is_default_mode = touch_input_context.get_category() == "DEFAULTMODE"; if( dist > ( get_option( "ANDROID_DEADZONE_RANGE" )*std::max( WindowWidth, @@ -3052,7 +3052,7 @@ static void CheckMessages() // If we've moved too far from joystick center, offset joystick center automatically float delta_x = finger_curr_x - finger_down_x; float delta_y = finger_curr_y - finger_down_y; - float dist = ( float )sqrtf( delta_x * delta_x + delta_y * delta_y ); + float dist = std::sqrt( delta_x * delta_x + delta_y * delta_y ); float max_dist = ( get_option( "ANDROID_DEADZONE_RANGE" ) + get_option( "ANDROID_REPEAT_DELAY_RANGE" ) ) * std::max( WindowWidth, WindowHeight ); if( dist > max_dist ) { @@ -3120,11 +3120,11 @@ static void CheckMessages() if( is_default_mode ) { float x1 = ( finger_curr_x - finger_down_x ); float y1 = ( finger_curr_y - finger_down_y ); - float d1 = ( float )( sqrtf( x1 * x1 + y1 * y1 ) ); + float d1 = std::sqrt( x1 * x1 + y1 * y1 ); float x2 = ( second_finger_curr_x - second_finger_down_x ); float y2 = ( second_finger_curr_y - second_finger_down_y ); - float d2 = ( float )( sqrtf( x2 * x2 + y2 * y2 ) ); + float d2 = std::sqrt( x2 * x2 + y2 * y2 ); float longest_window_edge = std::max( WindowWidth, WindowHeight ); @@ -3159,11 +3159,11 @@ static void CheckMessages() // both fingers heading in opposite direction, check for zoom gesture float down_x = finger_down_x - second_finger_down_x; float down_y = finger_down_y - second_finger_down_y; - float down_dist = ( float )sqrtf( down_x * down_x + down_y * down_y ); + float down_dist = std::sqrt( down_x * down_x + down_y * down_y ); float curr_x = finger_curr_x - second_finger_curr_x; float curr_y = finger_curr_y - second_finger_curr_y; - float curr_dist = ( float )sqrtf( curr_x * curr_x + curr_y * curr_y ); + float curr_dist = std::sqrt( curr_x * curr_x + curr_y * curr_y ); const float zoom_ratio = 0.9f; if( curr_dist < down_dist * zoom_ratio ) { diff --git a/src/simplexnoise.cpp b/src/simplexnoise.cpp index 117676c200451..684ce1b765ae9 100644 --- a/src/simplexnoise.cpp +++ b/src/simplexnoise.cpp @@ -187,13 +187,13 @@ float raw_noise_2d( const float x, const float y ) float n2 = 0; // Skew the input space to determine which simplex cell we're in - static const float F2 = 0.5f * ( sqrtf( 3.0f ) - 1.0f ); + static const float F2 = 0.5f * ( std::sqrt( 3.0f ) - 1.0f ); // Hairy factor for 2D float s = ( x + y ) * F2; int i = fastfloor( x + s ); int j = fastfloor( y + s ); - static const float G2 = ( 3.0f - sqrtf( 3.0f ) ) / 6.0f; + static const float G2 = ( 3.0f - std::sqrt( 3.0f ) ) / 6.0f; float t = ( i + j ) * G2; // Unskew the cell origin back to (x,y) space float X0 = i - t; @@ -397,8 +397,8 @@ float raw_noise_3d( const float x, const float y, const float z ) float raw_noise_4d( const float x, const float y, const float z, const float w ) { // The skewing and unskewing factors are hairy again for the 4D case - static const float F4 = ( sqrtf( 5.0f ) - 1.0f ) / 4.0f; - static const float G4 = ( 5.0f - sqrtf( 5.0f ) ) / 20.0f; + static const float F4 = ( std::sqrt( 5.0f ) - 1.0f ) / 4.0f; + static const float G4 = ( 5.0f - std::sqrt( 5.0f ) ) / 20.0f; float n0, n1, n2, n3, n4; // Noise contributions from the five corners // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in diff --git a/src/stats_tracker.h b/src/stats_tracker.h index 748820a03dd9e..7941d26ecf0d2 100644 --- a/src/stats_tracker.h +++ b/src/stats_tracker.h @@ -17,6 +17,7 @@ class JsonIn; class JsonOut; class event_statistic; class event_transformation; +enum class monotonically : int; class score; class stats_tracker; diff --git a/src/suffer.cpp b/src/suffer.cpp index 7d25989f9a0f6..fb6c5ad559301 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -1809,7 +1809,7 @@ void Character::apply_wetness_morale( int temperature ) if( bp_morale < 0 ) { // Damp, hot clothing on hot skin feels bad - scaled_temperature = fabs( scaled_temperature ); + scaled_temperature = std::fabs( scaled_temperature ); } // For an unmutated human swimming in deep water, this will add up to: diff --git a/src/teleport.cpp b/src/teleport.cpp index 10f3700fe8a31..33b53823bf757 100644 --- a/src/teleport.cpp +++ b/src/teleport.cpp @@ -44,8 +44,8 @@ bool teleport::teleport( Creature &critter, int min_distance, int max_distance, do { int rangle = rng( 0, 360 ); int rdistance = rng( min_distance, max_distance ); - new_pos.x = origin.x + rdistance * cos( rangle ); - new_pos.y = origin.y + rdistance * sin( rangle ); + 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 ); //handles teleporting into solids. diff --git a/src/tileray.cpp b/src/tileray.cpp index c1248bc60132a..3d595eadb7096 100644 --- a/src/tileray.cpp +++ b/src/tileray.cpp @@ -47,7 +47,7 @@ void tileray::init( int adir ) direction = ( adir < 0 ? 360 - ( ( -adir ) % 360 ) : adir % 360 ); last_d = point_zero; float direction_radians = static_cast( direction ) * M_PI / 180.0; - rl_vec2d delta_f( cos( direction_radians ), sin( direction_radians ) ); + rl_vec2d delta_f( std::cos( direction_radians ), std::sin( direction_radians ) ); delta = ( delta_f * 100 ).as_point(); abs_d = abs( delta ); steps = 0; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 15e577d6c8dd8..66a6ef6e89f0f 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1224,7 +1224,7 @@ int vehicle::part_vpower_w( const int index, const bool at_full_hp ) const double raddir = ( ( g->weather.winddirection + 180 ) % 360 ) * ( M_PI / 180 ); windvec = windvec.normalized(); windvec.y = -cos( raddir ); - windvec.x = sin( raddir ); + windvec.x = std::sin( raddir ); rl_vec2d fv = face_vec(); double dot = windvec.dot_product( fv ); if( dot <= 0 ) { @@ -3798,7 +3798,7 @@ void vehicle::noise_and_smoke( int load, time_duration time ) // Cap engine noise to avoid deafening. noise = std::min( noise, 100.0 ); // Even a vehicle with engines off will make noise traveling at high speeds - noise = std::max( noise, static_cast( fabs( velocity / 500.0 ) ) ); + noise = std::max( noise, static_cast( std::fabs( velocity / 500.0 ) ) ); int lvl = 0; if( one_in( 4 ) && rng( 0, 30 ) < noise ) { while( noise > sounds[lvl].second ) { diff --git a/src/vehicle_move.cpp b/src/vehicle_move.cpp index 9cbf417206e86..817bb206ff18a 100644 --- a/src/vehicle_move.cpp +++ b/src/vehicle_move.cpp @@ -91,7 +91,7 @@ int vehicle::slowdown( int at_velocity ) const } else if( !is_falling && !is_flying ) { double f_rolling_drag = coeff_rolling_drag() * ( vehicles::rolling_constant_to_variable + mps ); // increase rolling resistance by up to 25x if the vehicle is skidding at right angle to facing - const double skid_factor = 1 + 24 * std::abs( sin( DEGREES( face.dir() - move.dir() ) ) ); + const double skid_factor = 1 + 24 * std::abs( std::sin( DEGREES( face.dir() - move.dir() ) ) ); f_total_drag += f_rolling_drag * skid_factor; } double accel_slowdown = f_total_drag / to_kilogram( total_mass() ); @@ -1215,7 +1215,7 @@ rl_vec2d vehicle::velo_vec() const inline rl_vec2d degree_to_vec( double degrees ) { - return rl_vec2d( cos( degrees * M_PI / 180 ), sin( degrees * M_PI / 180 ) ); + return rl_vec2d( std::cos( degrees * M_PI / 180 ), std::sin( degrees * M_PI / 180 ) ); } // normalized. @@ -1466,7 +1466,7 @@ vehicle *vehicle::act_on_map() const float old_vel = vmiph_to_mps( vertical_velocity ); // Formula is v_2 = sqrt( 2*d*g + v_1^2 ) // Note: That drops the sign - const float new_vel = -sqrt( 2 * tile_height * g + old_vel * old_vel ); + const float new_vel = -std::sqrt( 2 * tile_height * g + old_vel * old_vel ); vertical_velocity = mps_to_vmiph( new_vel ); is_falling = true; } else { diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index 96ba9e7591c1f..7d82cd88798df 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -1498,6 +1498,7 @@ void vehicle::open_or_close( const int part_index, const bool opening ) } coeff_air_changed = true; + coeff_air_dirty = true; } void vehicle::use_autoclave( int p ) diff --git a/src/weather_gen.cpp b/src/weather_gen.cpp index 8233837038e2f..4f14b12c1beba 100644 --- a/src/weather_gen.cpp +++ b/src/weather_gen.cpp @@ -57,7 +57,7 @@ static weather_gen_common get_common_data( const tripoint &location, const time_ const double year_fraction( time_past_new_year( t ) / calendar::year_length() ); // [0,1) - result.cyf = cos( tau * ( year_fraction + .125 ) ); // [-1, 1] + result.cyf = std::cos( tau * ( year_fraction + .125 ) ); // [-1, 1] // We add one-eighth to line up `cyf` so that 1 is at // midwinter and -1 at midsummer. (Cataclsym DDA years // start when spring starts. Gregorian years start when @@ -79,7 +79,7 @@ static double weather_temperature_from_common_data( const weather_generator &wg, // -1 in midwinter, +1 in midsummer const season_type season = common.season; const double dayFraction = time_past_midnight( t ) / 1_days; - const double dayv = cos( tau * ( dayFraction + .5 - coldest_hour / 24 ) ); + const double dayv = std::cos( tau * ( dayFraction + .5 - coldest_hour / 24 ) ); // -1 at coldest_hour, +1 twelve hours later // manually specified seasonal temp variation from region_settings.json @@ -273,10 +273,10 @@ int weather_generator::get_water_temperature() const } // Temperature varies between 33.8F and 75.2F depending on the time of year. Day = 0 corresponds to the start of spring. - int annual_mean_water_temperature = 54.5 + 20.7 * sin( tau * ( day - season_length * 0.5 ) / + int annual_mean_water_temperature = 54.5 + 20.7 * std::sin( tau * ( day - season_length * 0.5 ) / ( season_length * 4.0 ) ); // Temperature varies between +2F and -2F depending on the time of day. Hour = 0 corresponds to midnight. - int daily_water_temperature_varaition = 2.0 + 2.0 * sin( tau * ( hour - 6.0 ) / 24.0 ); + int daily_water_temperature_varaition = 2.0 + 2.0 * std::sin( tau * ( hour - 6.0 ) / 24.0 ); water_temperature = annual_mean_water_temperature + daily_water_temperature_varaition; diff --git a/src/wish.cpp b/src/wish.cpp index 6c72695d5932b..5f76b9516d48e 100644 --- a/src/wish.cpp +++ b/src/wish.cpp @@ -497,9 +497,14 @@ class wish_item_callback: public uilist_callback } }; -void debug_menu::wishitem( player *p, int x, int y, int z ) +void debug_menu::wishitem( player *p ) { - if( p == nullptr && x <= 0 ) { + wishitem( p, tripoint( -1, -1, -1 ) ); +} + +void debug_menu::wishitem( player *p, const tripoint &pos ) +{ + if( p == nullptr && pos.x <= 0 ) { debugmsg( "game::wishitem(): invalid parameters" ); return; } @@ -569,8 +574,8 @@ void debug_menu::wishitem( player *p, int x, int y, int z ) } } p->invalidate_crafting_inventory(); - } else if( x >= 0 && y >= 0 ) { - g->m.add_item_or_charges( tripoint( x, y, z ), granted ); + } else if( pos.x >= 0 && pos.y >= 0 ) { + g->m.add_item_or_charges( pos, granted ); wmenu.ret = -1; } if( amount > 0 ) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5bf2c29e0f7b9..bfd56f6ecaf3a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,7 +4,7 @@ IF(BUILD_TESTING) IF(TILES) add_executable(cata_test-tiles ${CATACLYSM_DDA_TEST_SOURCES}) - target_link_libraries(cata_test-tiles libcataclysm-tiles) + target_link_libraries(cata_test-tiles cataclysm-tiles-common) add_test(NAME test-tiles COMMAND sh -c "$ -r cata --rng-seed `shuf -i 0-1000000000 -n 1`" @@ -14,7 +14,7 @@ IF(BUILD_TESTING) IF(CURSES) add_executable(cata_test ${CATACLYSM_DDA_TEST_SOURCES}) - target_link_libraries(cata_test libcataclysm) + target_link_libraries(cata_test cataclysm-common) add_test(NAME test COMMAND sh -c "$ -r cata --rng-seed `shuf -i 0-1000000000 -n 1`" diff --git a/tests/catch/catch.hpp b/tests/catch/catch.hpp index 94b5497e0c03c..a5149abd801b4 100644 --- a/tests/catch/catch.hpp +++ b/tests/catch/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.9.1 - * Generated: 2019-06-17 11:59:24.363643 + * Catch v2.12.0 + * Generated: 2020-04-21 16:27:54.138031 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,8 +15,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 9 -#define CATCH_VERSION_PATCH 1 +#define CATCH_VERSION_MINOR 12 +#define CATCH_VERSION_PATCH 0 #ifdef __clang__ # pragma clang system_header @@ -133,36 +133,55 @@ namespace Catch { #endif -#if defined(CATCH_CPP17_OR_GREATER) +#if defined(__cpp_lib_uncaught_exceptions) # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif -#ifdef __clang__ +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) #endif // __clang__ @@ -187,6 +206,7 @@ namespace Catch { // Android somehow still does not support std::to_string #if defined(__ANDROID__) # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE #endif //////////////////////////////////////////////////////////////////////////////// @@ -220,14 +240,17 @@ namespace Catch { //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) # if _MSC_VER >= 1900 // Visual Studio 2015 or newer # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS # endif // Universal Windows platform does not support SEH -// Or console colors (or console at all...) +// Or console colours (or console at all...) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # define CATCH_CONFIG_COLOUR_NONE # else @@ -237,9 +260,12 @@ namespace Catch { // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + #endif // _MSC_VER #if defined(_REENTRANT) || defined(_MSC_VER) @@ -277,40 +303,53 @@ namespace Catch { #endif //////////////////////////////////////////////////////////////////////////////// -// Check if string_view is available and usable -// The check is split apart to work around v140 (VS2015) preprocessor issue... -#if defined(__has_include) -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW -#endif + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE #endif -//////////////////////////////////////////////////////////////////////////////// -// Check if optional is available and usable -#if defined(__has_include) -# if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif -//////////////////////////////////////////////////////////////////////////////// -// Check if variant is available and usable +// Various stdlib support checks that require __has_include #if defined(__has_include) -# if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 -# include -# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# define CATCH_CONFIG_NO_CPP17_VARIANT -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__clang__) && (__clang_major__ < 8) -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER @@ -347,6 +386,10 @@ namespace Catch { # define CATCH_CONFIG_CPP17_VARIANT #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif @@ -363,25 +406,53 @@ namespace Catch { # define CATCH_CONFIG_POLYFILL_ISNAN #endif -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) # define CATCH_CONFIG_USE_ASYNC #endif +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -446,7 +517,7 @@ namespace Catch { SourceLineInfo( SourceLineInfo&& ) noexcept = default; SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - bool empty() const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator < ( SourceLineInfo const& other ) const noexcept; @@ -487,9 +558,10 @@ namespace Catch { } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -516,6 +588,7 @@ namespace Catch { virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); @@ -528,53 +601,30 @@ namespace Catch { #include #include #include +#include namespace Catch { /// A non-owning string class (similar to the forthcoming std::string_view) /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. + /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; + using const_iterator = const char*; private: - friend struct StringRefTestAccess; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} - - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + char const* m_start = s_empty; + size_type m_size = 0; - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + public: // construction + constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept + constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} @@ -584,101 +634,64 @@ namespace Catch { m_size( stdString.size() ) {} - ~StringRef() noexcept { - delete[] m_data; + explicit operator std::string() const { + return std::string(m_start, m_size); } - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; - } - - operator std::string() const; - - void swap( StringRef& other ) noexcept; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } public: // named queries - auto empty() const noexcept -> bool { + constexpr auto empty() const noexcept -> bool { return m_size == 0; } - auto size() const noexcept -> size_type { + constexpr auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception auto c_str() const -> char const*; public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } - } // namespace Catch -inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { return Catch::StringRef( rawChars, size ); } // end catch_stringref.h -// start catch_type_traits.hpp - - -#include - -namespace Catch{ - -#ifdef CATCH_CPP17_OR_GREATER - template - inline constexpr auto is_unique = std::true_type{}; - - template - inline constexpr auto is_unique = std::bool_constant< - (!std::is_same_v && ...) && is_unique - >{}; -#else - -template -struct is_unique : std::true_type{}; - -template -struct is_unique : std::integral_constant -::value - && is_unique::value - && is_unique::value ->{}; - -#endif -} - -// end catch_type_traits.hpp // start catch_preprocessor.hpp @@ -775,35 +788,49 @@ struct is_unique : std::integral_constant template struct TypeList {};\ template\ constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ \ - template class L1, typename...E1, template class L2, typename...E2> \ - constexpr auto append(L1, L2) noexcept -> L1 { return {}; }\ + template \ + struct append { using type = T; };\ template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - constexpr auto append(L1, L2, Rest...) noexcept -> decltype(append(L1{}, Rest{}...)) { return {}; }\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ template< template class L1, typename...E1, typename...Rest>\ - constexpr auto append(L1, TypeList, Rest...) noexcept -> L1 { return {}; }\ + struct append, TypeList, Rest...> { using type = L1; };\ \ template< template class Container, template class List, typename...elems>\ - constexpr auto rewrap(List) noexcept -> TypeList> { return {}; }\ + struct rewrap, List> { using type = TypeList>; };\ template< template class Container, template class List, class...Elems, typename...Elements>\ - constexpr auto rewrap(List,Elements...) noexcept -> decltype(append(TypeList>{}, rewrap(Elements{}...))) { return {}; }\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ \ template