From 70efa4b401a29c86494337eb2a4a0569391af5da Mon Sep 17 00:00:00 2001 From: RobbieNeko <30732426+RobbieNeko@users.noreply.github.com> Date: Sat, 23 Sep 2023 16:46:38 -0400 Subject: [PATCH 01/28] BIOPROOF distribution: Robots (#3227) * BIOPROOF distribution: Robots * style(autofix.ci): automated formatting --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- data/json/monsters/defense_bot.json | 62 ++++++++++++++++++++++++----- data/json/monsters/drones.json | 2 +- data/json/monsters/turrets.json | 25 +++++++++--- data/json/monsters/utility_bot.json | 48 ++++++++++++++++++---- 4 files changed, 113 insertions(+), 24 deletions(-) diff --git a/data/json/monsters/defense_bot.json b/data/json/monsters/defense_bot.json index b2ef5c2ab28d..618feea8cd93 100644 --- a/data/json/monsters/defense_bot.json +++ b/data/json/monsters/defense_bot.json @@ -31,7 +31,17 @@ "special_attacks": [ [ "COPBOT", 3 ] ], "death_drops": { "groups": [ [ "robots", 4 ], [ "copbot", 1 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "BASHES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_1" ] + "flags": [ + "SEES", + "HEARS", + "BASHES", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PRIORITIZE_TARGETS", + "PATH_AVOID_DANGER_1", + "BIOPROOF" + ] }, { "id": "mon_riotbot", @@ -63,7 +73,17 @@ "special_when_hit": [ "ZAPBACK", 100 ], "death_drops": { "groups": [ [ "robots", 4 ], [ "copbot", 1 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "GOODHEARING", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_1" ] + "flags": [ + "SEES", + "HEARS", + "GOODHEARING", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PRIORITIZE_TARGETS", + "PATH_AVOID_DANGER_1", + "BIOPROOF" + ] }, { "id": "mon_secubot", @@ -113,7 +133,17 @@ ], "death_drops": { }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PATH_AVOID_DANGER_1", "LOUDMOVES", "DROPS_AMMO" ] + "flags": [ + "SEES", + "HEARS", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PATH_AVOID_DANGER_1", + "LOUDMOVES", + "DROPS_AMMO", + "BIOPROOF" + ] }, { "id": "mon_talon_m202a1", @@ -163,7 +193,17 @@ ], "death_drops": { }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PATH_AVOID_DANGER_1", "LOUDMOVES", "DROPS_AMMO" ] + "flags": [ + "SEES", + "HEARS", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PATH_AVOID_DANGER_1", + "LOUDMOVES", + "DROPS_AMMO", + "BIOPROOF" + ] }, { "id": "mon_skitterbot", @@ -193,7 +233,7 @@ "special_attacks": [ [ "TAZER", 5 ] ], "death_drops": { "groups": [ [ "robots", 4 ], [ "skitterbot", 1 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "GOODHEARING", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PATH_AVOID_DANGER_1" ] + "flags": [ "SEES", "HEARS", "GOODHEARING", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PATH_AVOID_DANGER_1", "BIOPROOF" ] }, { "id": "mon_science_bot", @@ -239,7 +279,8 @@ "NO_BREATHE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2", - "DROPS_AMMO" + "DROPS_AMMO", + "BIOPROOF" ] }, { @@ -282,7 +323,8 @@ "NO_BREATHE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2", - "LOUDMOVES" + "LOUDMOVES", + "BIOPROOF" ] }, { @@ -327,7 +369,8 @@ "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2", "LOUDMOVES", - "DROPS_AMMO" + "DROPS_AMMO", + "BIOPROOF" ] }, { @@ -372,7 +415,8 @@ "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2", "LOUDMOVES", - "DROPS_AMMO" + "DROPS_AMMO", + "BIOPROOF" ] } ] diff --git a/data/json/monsters/drones.json b/data/json/monsters/drones.json index 1d0b2a0e9a26..5f74ad07b536 100644 --- a/data/json/monsters/drones.json +++ b/data/json/monsters/drones.json @@ -15,7 +15,7 @@ "luminance": 5, "death_drops": { "subtype": "collection", "groups": [ [ "robots", 80 ] ], "//": "80% chance of an item from group robots" }, "death_function": [ "BROKEN_AMMO" ], - "flags": [ "SEES", "FLIES", "NOHEAD", "ELECTRONIC", "NO_BREATHE", "INTERIOR_AMMO" ] + "flags": [ "SEES", "FLIES", "NOHEAD", "ELECTRONIC", "NO_BREATHE", "INTERIOR_AMMO", "BIOPROOF" ] }, { "id": "mon_EMP_hack", diff --git a/data/json/monsters/turrets.json b/data/json/monsters/turrets.json index 396a7007c888..f74755395a37 100644 --- a/data/json/monsters/turrets.json +++ b/data/json/monsters/turrets.json @@ -26,7 +26,7 @@ "special_attacks": [ [ "SEARCHLIGHT", 1 ] ], "death_drops": { "groups": [ [ "robots", 1 ], [ "turret_searchlight", 1 ] ] }, "death_function": [ "FOCUSEDBEAM" ], - "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "COLDPROOF", "IMMOBILE", "NO_BREATHE", "PRIORITIZE_TARGETS" ] + "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "COLDPROOF", "IMMOBILE", "NO_BREATHE", "PRIORITIZE_TARGETS", "BIOPROOF" ] }, { "id": "mon_laserturret", @@ -66,7 +66,17 @@ "special_when_hit": [ "RETURN_FIRE", 100 ], "death_drops": { }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "COLDPROOF", "IMMOBILE", "NO_BREATHE", "ID_CARD_DESPAWN", "CONSOLE_DESPAWN" ] + "flags": [ + "SEES", + "NOHEAD", + "ELECTRONIC", + "COLDPROOF", + "IMMOBILE", + "NO_BREATHE", + "ID_CARD_DESPAWN", + "CONSOLE_DESPAWN", + "BIOPROOF" + ] }, { "id": "mon_turret_riot", @@ -120,7 +130,7 @@ ], "death_drops": { }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "COLDPROOF", "IMMOBILE", "NO_BREATHE", "DROPS_AMMO" ] + "flags": [ "SEES", "NOHEAD", "ELECTRONIC", "COLDPROOF", "IMMOBILE", "NO_BREATHE", "DROPS_AMMO", "BIOPROOF" ] }, { "id": "mon_turret_light", @@ -183,7 +193,8 @@ "NO_BREATHE", "DROPS_AMMO", "ID_CARD_DESPAWN", - "CONSOLE_DESPAWN" + "CONSOLE_DESPAWN", + "BIOPROOF" ] }, { @@ -247,7 +258,8 @@ "NO_BREATHE", "DROPS_AMMO", "ID_CARD_DESPAWN", - "CONSOLE_DESPAWN" + "CONSOLE_DESPAWN", + "BIOPROOF" ] }, { @@ -311,7 +323,8 @@ "NO_BREATHE", "DROPS_AMMO", "CONSOLE_DESPAWN", - "ID_CARD_DESPAWN" + "ID_CARD_DESPAWN", + "BIOPROOF" ] } ] diff --git a/data/json/monsters/utility_bot.json b/data/json/monsters/utility_bot.json index 169da985574c..f4573fecce83 100644 --- a/data/json/monsters/utility_bot.json +++ b/data/json/monsters/utility_bot.json @@ -25,7 +25,7 @@ "special_attacks": [ [ "PHOTOGRAPH", 30 ] ], "death_drops": { "groups": [ [ "robots", 4 ], [ "eyebot", 1 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "FLIES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "NOHEAD", "PRIORITIZE_TARGETS" ] + "flags": [ "SEES", "FLIES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "NOHEAD", "PRIORITIZE_TARGETS", "BIOPROOF" ] }, { "id": "mon_grocerybot", @@ -61,7 +61,8 @@ "PACIFIST", "PAY_BOT", "PET_HARNESSABLE", - "PATH_AVOID_DANGER_2" + "PATH_AVOID_DANGER_2", + "BIOPROOF" ] }, { @@ -88,7 +89,7 @@ "special_attacks": [ [ "PAID_BOT", 1 ] ], "death_drops": { "groups": [ [ "robots", 4 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PUSH_MON", "HEARS", "PACIFIST", "PAY_BOT" ] + "flags": [ "SEES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PUSH_MON", "HEARS", "PACIFIST", "PAY_BOT", "BIOPROOF" ] }, { "id": "mon_hazmatbot", @@ -113,7 +114,17 @@ "vision_day": 50, "revert_to_itype": "bot_hazmatbot", "death_function": [ "EXPLODE" ], - "flags": [ "SEES", "HEARS", "BASHES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_1" ] + "flags": [ + "SEES", + "HEARS", + "BASHES", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PRIORITIZE_TARGETS", + "PATH_AVOID_DANGER_1", + "BIOPROOF" + ] }, { "id": "mon_haulerbot", @@ -139,7 +150,17 @@ "vision_day": 50, "revert_to_itype": "bot_haulerbot", "death_function": [ "BROKEN" ], - "flags": [ "SEES", "HEARS", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PATH_AVOID_DANGER_2", "PACIFIST", "PET_HARNESSABLE" ] + "flags": [ + "SEES", + "HEARS", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PATH_AVOID_DANGER_2", + "PACIFIST", + "PET_HARNESSABLE", + "BIOPROOF" + ] }, { "id": "mon_molebot", @@ -168,7 +189,7 @@ "revert_to_itype": "bot_molebot", "death_drops": { "groups": [ [ "robots", 4 ], [ "molebot", 1 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "HEARS", "GOODHEARING", "DIGS", "NO_BREATHE", "ELECTRONIC", "COLDPROOF", "PATH_AVOID_DANGER_1" ] + "flags": [ "HEARS", "GOODHEARING", "DIGS", "NO_BREATHE", "ELECTRONIC", "COLDPROOF", "PATH_AVOID_DANGER_1", "BIOPROOF" ] }, { "//": "nurse_bot and nurse_bot_defective look very similar, part of the trick is figuring out which one is the good one. So the sprites should probably look pretty similar to not give it away immediately", @@ -198,7 +219,7 @@ "special_attacks": [ [ "ASSIST", 30 ], [ "CHECK_UP", 120 ] ], "death_drops": { "groups": [ [ "robots", 4 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PUSH_MON", "HEARS", "PACIFIST" ] + "flags": [ "SEES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PUSH_MON", "HEARS", "PACIFIST", "BIOPROOF" ] }, { "//": "nurse_bot and nurse_bot_defective look very similar, part of the trick is figuring out which one is the good one. So the sprites should probably look pretty similar to not give it away immediately", @@ -231,6 +252,17 @@ "special_attacks": [ [ "OPERATE", 30 ], [ "PARROT", 20 ] ], "death_drops": { "groups": [ [ "robots", 4 ] ] }, "death_function": [ "BROKEN" ], - "flags": [ "SEES", "ELECTRONIC", "COLDPROOF", "NO_BREATHE", "PUSH_MON", "HEARS", "PACIFIST", "GRABS", "INTERIOR_AMMO" ] + "flags": [ + "SEES", + "ELECTRONIC", + "COLDPROOF", + "NO_BREATHE", + "PUSH_MON", + "HEARS", + "PACIFIST", + "GRABS", + "INTERIOR_AMMO", + "BIOPROOF" + ] } ] From 7ac04c1b3e1257d578c4f1c472f329a9c4a16290 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sat, 23 Sep 2023 17:46:02 -0500 Subject: [PATCH 02/28] Fix NPCs set to attack what you attack charging blindly (#3226) --- src/npcmove.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 41a674f91456..a84a864ca6ac 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -1361,6 +1361,8 @@ npc_action npc::method_of_attack() bool can_use_gun = ( ( !is_player_ally() || rules.has_flag( ally_rule::use_guns ) ) && ( ai_cache.danger >= 3 || emergency() || dist < 0 ) ); bool use_silent = ( is_player_ally() && rules.has_flag( ally_rule::use_silent ) ); + const bool not_engaged_yet = !critter->has_effect( effect_hit_by_player ) && + rules.engagement == combat_engagement::HIT; // if there's enough of a threat to be here, power up the combat CBMs activate_combat_cbms(); @@ -1428,7 +1430,7 @@ npc_action npc::method_of_attack() return npc_aim; } add_msg( m_debug, "%s can't figure out what to do", disp_name() ); - return ( dont_move || !same_z ) ? npc_undecided : npc_melee; + return ( dont_move || !same_z || not_engaged_yet ) ? npc_undecided : npc_melee; } npc_action npc::address_needs() From 96097159139cad7661a5d0698f5a02fed2955d59 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sat, 23 Sep 2023 19:27:06 -0500 Subject: [PATCH 03/28] Allow steel and superalloy lining for more items (#3228) --- data/json/items/armor/arms_armor.json | 2 ++ data/json/items/armor/boots.json | 1 + data/json/items/armor/cloaks.json | 1 + data/json/items/armor/coats.json | 11 +++++++++++ data/json/items/armor/gloves.json | 4 ++++ data/json/items/armor/helmets.json | 3 +++ data/json/items/armor/legs_armor.json | 5 +++++ data/json/items/armor/legs_clothes.json | 3 +++ data/json/items/armor/masks.json | 2 ++ data/json/items/armor/suits_clothes.json | 4 ++++ data/json/items/armor/suits_protection.json | 2 ++ data/json/items/armor/torso_armor.json | 3 +++ data/json/items/armor/torso_clothes.json | 2 ++ data/json/items/armor/undergarment.json | 1 + 14 files changed, 44 insertions(+) diff --git a/data/json/items/armor/arms_armor.json b/data/json/items/armor/arms_armor.json index e1036d965564..9939017eb0b4 100644 --- a/data/json/items/armor/arms_armor.json +++ b/data/json/items/armor/arms_armor.json @@ -244,6 +244,7 @@ "covers": [ "arms" ], "coverage": 30, "material_thickness": 5, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "WATER_FRIENDLY", "BELTED" ] }, { @@ -266,6 +267,7 @@ "warmth": 10, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "STURDY", "BELTED", "WATER_FRIENDLY" ] } ] diff --git a/data/json/items/armor/boots.json b/data/json/items/armor/boots.json index 057582940306..3a5e3b9cc9c3 100644 --- a/data/json/items/armor/boots.json +++ b/data/json/items/armor/boots.json @@ -81,6 +81,7 @@ "warmth": 35, "material_thickness": 3, "environmental_protection": 8, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF", "STURDY" ] }, { diff --git a/data/json/items/armor/cloaks.json b/data/json/items/armor/cloaks.json index ff16debbe66c..467926fd205b 100644 --- a/data/json/items/armor/cloaks.json +++ b/data/json/items/armor/cloaks.json @@ -224,6 +224,7 @@ "warmth": 35, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "OUTER" ] }, { diff --git a/data/json/items/armor/coats.json b/data/json/items/armor/coats.json index 36187eb99fab..dceeb33781e3 100644 --- a/data/json/items/armor/coats.json +++ b/data/json/items/armor/coats.json @@ -220,6 +220,7 @@ "warmth": 15, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -437,6 +438,7 @@ "storage": "1250 ml", "warmth": 25, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "OUTER", "VARSIZE" ] }, { @@ -481,6 +483,7 @@ "storage": "1 L", "warmth": 35, "material_thickness": 4, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -509,6 +512,7 @@ "text": "A jacket made from denim. Provides decent protection from cuts. This one is haphazardly covered with patches featuring metal band logos." } ], + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -623,6 +627,7 @@ "encumbrance": 10, "warmth": 10, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY" ] }, { @@ -643,6 +648,7 @@ "coverage": 80, "warmth": 5, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY" ] }, { @@ -686,6 +692,7 @@ "coverage": 80, "warmth": 5, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY" ] }, { @@ -868,6 +875,7 @@ "warmth": 15, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -978,6 +986,7 @@ "warmth": 15, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -1131,6 +1140,7 @@ "warmth": 15, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "OUTER" ] }, { @@ -1278,6 +1288,7 @@ "storage": "2 L", "warmth": 30, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "SUPER_FANCY" ] }, { diff --git a/data/json/items/armor/gloves.json b/data/json/items/armor/gloves.json index bb77b6f635ca..5c7fa1f77fdd 100644 --- a/data/json/items/armor/gloves.json +++ b/data/json/items/armor/gloves.json @@ -85,6 +85,7 @@ "warmth": 25, "material_thickness": 4, "environmental_protection": 6, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY", "WATERPROOF" ] }, { @@ -142,6 +143,7 @@ "warmth": 15, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "STURDY" ] }, { @@ -164,6 +166,7 @@ "warmth": 15, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "STURDY" ] }, { @@ -709,6 +712,7 @@ "warmth": 25, "material_thickness": 3, "environmental_protection": 5, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "WATERPROOF", "STURDY" ] }, { diff --git a/data/json/items/armor/helmets.json b/data/json/items/armor/helmets.json index 067f2952b365..5f7e59151f2e 100644 --- a/data/json/items/armor/helmets.json +++ b/data/json/items/armor/helmets.json @@ -495,6 +495,7 @@ "warmth": 35, "material_thickness": 3, "environmental_protection": 4, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF", "SUN_GLASSES" ] }, { @@ -540,6 +541,7 @@ "warmth": 40, "material_thickness": 3, "environmental_protection": 7, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY", "WATERPROOF", "SUN_GLASSES" ] }, { @@ -701,6 +703,7 @@ "encumbrance": 20, "warmth": 15, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "FANCY", "STAB" ] }, { diff --git a/data/json/items/armor/legs_armor.json b/data/json/items/armor/legs_armor.json index 0dc31bf6b615..712a955efe36 100644 --- a/data/json/items/armor/legs_armor.json +++ b/data/json/items/armor/legs_armor.json @@ -86,6 +86,7 @@ "encumbrance": 3, "warmth": 10, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "OUTER" ] }, { @@ -108,6 +109,7 @@ "storage": "500 ml", "warmth": 20, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE" ] }, { @@ -127,6 +129,7 @@ "covers": [ "legs" ], "coverage": 30, "material_thickness": 5, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "WATER_FRIENDLY", "BELTED" ] }, { @@ -278,6 +281,7 @@ "warmth": 12, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF", "POCKETS", "RAINPROOF", "STURDY" ] }, { @@ -300,6 +304,7 @@ "warmth": 35, "material_thickness": 3, "environmental_protection": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF" ] }, { diff --git a/data/json/items/armor/legs_clothes.json b/data/json/items/armor/legs_clothes.json index 9f931d1b76c5..37bd04cb8873 100644 --- a/data/json/items/armor/legs_clothes.json +++ b/data/json/items/armor/legs_clothes.json @@ -141,6 +141,7 @@ "storage": "500 ml", "warmth": 10, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS" ] }, { @@ -164,6 +165,7 @@ "storage": "500 ml", "warmth": 10, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS", "FANCY" ] }, { @@ -361,6 +363,7 @@ "storage": "2500 ml", "warmth": 20, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "POCKETS" ] }, { diff --git a/data/json/items/armor/masks.json b/data/json/items/armor/masks.json index 2b8b4c96dd18..6b719727f4e3 100644 --- a/data/json/items/armor/masks.json +++ b/data/json/items/armor/masks.json @@ -169,6 +169,7 @@ "warmth": 5, "material_thickness": 1, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "WATER_FRIENDLY" ] }, { @@ -193,6 +194,7 @@ "warmth": 5, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "WATER_FRIENDLY", "STURDY" ] }, { diff --git a/data/json/items/armor/suits_clothes.json b/data/json/items/armor/suits_clothes.json index 32d72c56292d..053893911ab1 100644 --- a/data/json/items/armor/suits_clothes.json +++ b/data/json/items/armor/suits_clothes.json @@ -20,6 +20,7 @@ "warmth": 30, "material_thickness": 2, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "SKINTIGHT" ] }, { @@ -67,6 +68,7 @@ "warmth": 50, "material_thickness": 5, "environmental_protection": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "OUTER" ] }, { @@ -187,6 +189,7 @@ "warmth": 50, "material_thickness": 7, "environmental_protection": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "OUTER" ] }, { @@ -208,6 +211,7 @@ "encumbrance": 20, "warmth": 50, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE" ] }, { diff --git a/data/json/items/armor/suits_protection.json b/data/json/items/armor/suits_protection.json index e30b6d2c580c..86c5c8638bdf 100644 --- a/data/json/items/armor/suits_protection.json +++ b/data/json/items/armor/suits_protection.json @@ -618,6 +618,7 @@ "storage": "7500 ml", "warmth": 15, "material_thickness": 4, + "valid_mods": [ "steel_padded", "alloy_padded" ], "environmental_protection": 3, "flags": [ "VARSIZE", "WATERPROOF", "POCKETS", "HOOD", "RAINPROOF", "STURDY" ] }, @@ -707,6 +708,7 @@ "storage": "2500 ml", "warmth": 25, "material_thickness": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "FANCY", "POCKETS" ] }, { diff --git a/data/json/items/armor/torso_armor.json b/data/json/items/armor/torso_armor.json index a1ed7f388dc7..dc5fa5791b02 100644 --- a/data/json/items/armor/torso_armor.json +++ b/data/json/items/armor/torso_armor.json @@ -40,6 +40,7 @@ "encumbrance": 20, "warmth": 20, "material_thickness": 8, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "STURDY" ] }, { @@ -329,6 +330,7 @@ "warmth": 15, "material_thickness": 4, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF", "RAINPROOF", "STURDY" ] }, { @@ -353,6 +355,7 @@ "warmth": 35, "material_thickness": 4, "environmental_protection": 2, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "WATERPROOF" ] }, { diff --git a/data/json/items/armor/torso_clothes.json b/data/json/items/armor/torso_clothes.json index 5eb4bdd58178..c5a0bdba2344 100644 --- a/data/json/items/armor/torso_clothes.json +++ b/data/json/items/armor/torso_clothes.json @@ -20,6 +20,7 @@ "warmth": 15, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "POCKETS", "BELTED", "WATER_FRIENDLY" ] }, { @@ -234,6 +235,7 @@ "storage": "2250 ml", "warmth": 30, "material_thickness": 3, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "OUTER", "POCKETS", "HOOD" ] }, { diff --git a/data/json/items/armor/undergarment.json b/data/json/items/armor/undergarment.json index 15409eda6e07..261fa5e89047 100644 --- a/data/json/items/armor/undergarment.json +++ b/data/json/items/armor/undergarment.json @@ -328,6 +328,7 @@ "warmth": 25, "material_thickness": 3, "environmental_protection": 1, + "valid_mods": [ "steel_padded", "alloy_padded" ], "flags": [ "VARSIZE", "FANCY", "SKINTIGHT" ] }, { From a5e79b74f5431ce655056373c606588e0ab19371 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sat, 23 Sep 2023 19:30:47 -0500 Subject: [PATCH 04/28] Add some more basic armor items (#3221) * Add some more basic armor items * Update masks.json --- .../itemgroups/Clothing_Gear/clothing.json | 9 +++++ .../Locations_MapExtras/mansion.json | 25 ++++++++++-- data/json/itemgroups/art_antiques_crafts.json | 1 + data/json/items/armor/arms_armor.json | 13 +++++++ data/json/items/armor/helmets.json | 22 +++++++++++ data/json/items/armor/masks.json | 33 ++++++++++++++++ data/json/recipes/armor/arms.json | 13 +++++++ data/json/recipes/armor/head.json | 39 +++++++++++++++++++ 8 files changed, 152 insertions(+), 3 deletions(-) diff --git a/data/json/itemgroups/Clothing_Gear/clothing.json b/data/json/itemgroups/Clothing_Gear/clothing.json index bcda33d14575..83f6286c4de0 100644 --- a/data/json/itemgroups/Clothing_Gear/clothing.json +++ b/data/json/itemgroups/Clothing_Gear/clothing.json @@ -2025,6 +2025,7 @@ [ "modularvestsuper", 1 ], [ "dump_pouch", 20 ], [ "mask_bal", 5 ], + [ "mask_cavalry_iron", 2 ], [ "vest", 15 ], [ "gloves_fingerless", 15 ], [ "gloves_light_fingerless", 5 ], @@ -2379,6 +2380,7 @@ [ "duffelbag", 8 ], [ "mask_h20survivor", 1 ], [ "mask_bal", 14 ], + [ "mask_cavalry_iron", 4 ], [ "mask_hockey", 26 ], [ "mask_gas", 24 ], [ "mask_filter", 12 ], @@ -2469,11 +2471,14 @@ [ "helmet_larmor", 40 ], [ "helmet_nasal", 50 ], [ "helmet_galea", 40 ], + [ "mask_cavalry_iron", 10 ], + [ "mask_cavalry_bronze", 10 ], [ "boots_larmor", 40 ], [ "armor_larmor", 40 ], [ "armguard_larmor", 40 ], [ "vambrace_larmor", 20 ], [ "gambeson", 50 ], + [ "cap_arming", 25 ], [ "legguard_metal", 10 ], [ "helmet_corinthian", 45 ], [ "armor_cuirass", 25 ], @@ -2523,6 +2528,9 @@ [ "helmet_larmor", 40 ], [ "helmet_nasal", 50 ], [ "helmet_galea", 40 ], + [ "mask_cavalry_iron", 10 ], + [ "mask_cavalry_bronze", 10 ], + [ "cap_arming", 25 ], [ "chainmail_hood", 30 ] ] }, @@ -2530,6 +2538,7 @@ "type": "item_group", "id": "museum_armor_arms", "items": [ + [ "armguard_bronze", 10 ], [ "armguard_lightplate", 30 ], [ "armguard_larmor", 40 ], [ "vambrace_larmor", 20 ], diff --git a/data/json/itemgroups/Locations_MapExtras/mansion.json b/data/json/itemgroups/Locations_MapExtras/mansion.json index 8f389c0b68a2..bd0b68898447 100644 --- a/data/json/itemgroups/Locations_MapExtras/mansion.json +++ b/data/json/itemgroups/Locations_MapExtras/mansion.json @@ -448,7 +448,13 @@ "id": "soa_decor", "type": "item_group", "subtype": "collection", - "items": [ { "group": "soa_weapons_decor" }, [ "armor_plate", 100 ], [ "helmet_plate", 100 ] ] + "items": [ + { "group": "soa_weapons_decor" }, + [ "gambeson", 50 ], + [ "armor_plate", 100 ], + [ "cap_arming", 50 ], + [ "helmet_plate", 100 ] + ] }, { "id": "soa_weapons_decor", @@ -467,7 +473,9 @@ "items": [ { "group": "soa_weapons_plate" }, { "group": "soa_shields_plate", "prob": 25 }, + [ "gambeson", 50 ], [ "armor_lightplate", 100 ], + [ "cap_arming", 50 ], [ "helmet_barbute", 100 ] ] }, @@ -490,7 +498,12 @@ "id": "soa_mail", "type": "item_group", "subtype": "collection", - "items": [ { "group": "soa_weapons_mail" }, { "group": "soa_shields_mail", "prob": 50 }, [ "chainmail_suit", 100 ] ] + "items": [ + { "group": "soa_weapons_mail" }, + { "group": "soa_shields_mail", "prob": 50 }, + [ "cap_arming", 50 ], + [ "chainmail_suit", 100 ] + ] }, { "id": "soa_weapons_mail", @@ -517,7 +530,13 @@ "id": "soa_samurai", "type": "item_group", "subtype": "collection", - "items": [ { "group": "soa_weapons_samurai" }, [ "scabbard", 50 ], [ "armor_samurai", 100 ], [ "helmet_kabuto", 100 ] ] + "items": [ + { "group": "soa_weapons_samurai" }, + [ "scabbard", 50 ], + [ "armor_samurai", 100 ], + [ "cap_arming", 50 ], + [ "helmet_kabuto", 100 ] + ] }, { "id": "soa_weapons_samurai", diff --git a/data/json/itemgroups/art_antiques_crafts.json b/data/json/itemgroups/art_antiques_crafts.json index ba5a4747ac96..4f59a613bf46 100644 --- a/data/json/itemgroups/art_antiques_crafts.json +++ b/data/json/itemgroups/art_antiques_crafts.json @@ -97,6 +97,7 @@ { "item": "nodachi_inferior", "prob": 2 }, { "item": "knife_baselard", "prob": 2 }, { "item": "gambeson", "prob": 3 }, + { "item": "cap_arming", "prob": 2 }, { "item": "tunic", "prob": 1 }, { "item": "armor_lamellar", "prob": 2 }, { "item": "armor_lightplate", "prob": 1 }, diff --git a/data/json/items/armor/arms_armor.json b/data/json/items/armor/arms_armor.json index 9939017eb0b4..6a028c0fbf12 100644 --- a/data/json/items/armor/arms_armor.json +++ b/data/json/items/armor/arms_armor.json @@ -141,6 +141,19 @@ "environmental_protection": 1, "flags": [ "BELTED", "BLOCK_WHILE_WORN", "WATER_FRIENDLY" ] }, + { + "id": "armguard_bronze", + "copy-from": "armguard_metal", + "type": "ARMOR", + "name": { "str": "pair of bronze arm guards", "str_pl": "pairs of arm guards" }, + "description": "A pair of arm guards hammered out from sheets of bronze, for a classical take on the Post-Apocalyptic Warrior look.", + "weight": "1500 g", + "price": "400 USD", + "price_postapoc": "12 USD", + "material": [ "bronze" ], + "color": "yellow", + "encumbrance": 20 + }, { "id": "armguard_paper", "type": "ARMOR", diff --git a/data/json/items/armor/helmets.json b/data/json/items/armor/helmets.json index 5f7e59151f2e..cfdc66ab11ca 100644 --- a/data/json/items/armor/helmets.json +++ b/data/json/items/armor/helmets.json @@ -405,6 +405,28 @@ "material_thickness": 2, "flags": [ "VARSIZE", "SKINTIGHT" ] }, + { + "id": "cap_arming", + "repairs_like": "gambeson", + "type": "ARMOR", + "name": { "str": "arming cap" }, + "description": "This goes inside a helmet to help keep your head warm in cold climates.", + "weight": "165 g", + "volume": "250 ml", + "price": "20 USD", + "price_postapoc": "250 cent", + "material": [ "cotton" ], + "symbol": "[", + "looks_like": "helmet_liner", + "color": "light_gray", + "covers": [ "head" ], + "coverage": 90, + "encumbrance": 15, + "warmth": 30, + "material_thickness": 5, + "valid_mods": [ "steel_padded", "alloy_padded" ], + "flags": [ "VARSIZE", "SKINTIGHT", "STURDY" ] + }, { "id": "helmet_lobster", "repairs_like": "xlkevlar", diff --git a/data/json/items/armor/masks.json b/data/json/items/armor/masks.json index 6b719727f4e3..d7f67b185aa1 100644 --- a/data/json/items/armor/masks.json +++ b/data/json/items/armor/masks.json @@ -127,6 +127,39 @@ "environmental_protection": 1, "flags": [ "WATER_FRIENDLY", "STURDY" ] }, + { + "id": "mask_cavalry_iron", + "repairs_like": "helmet_plarmor", + "type": "ARMOR", + "name": { "str": "iron battle mask" }, + "description": "A full-face mask made of iron, in the vein of Roman cavalry masks. Provides decent protection and gives an imposing post-apocalyptic look.", + "weight": "900 g", + "volume": "750 ml", + "price": "300 USD", + "price_postapoc": "5 USD", + "material": [ "iron" ], + "symbol": "[", + "looks_like": "mask_bal", + "color": "dark_gray", + "covers": [ "mouth", "eyes" ], + "coverage": 95, + "encumbrance": 15, + "warmth": 10, + "material_thickness": 3, + "environmental_protection": 1, + "flags": [ "STURDY" ] + }, + { + "id": "mask_cavalry_bronze", + "copy-from": "mask_cavalry_iron", + "type": "ARMOR", + "name": { "str": "bronze battle mask" }, + "description": "A full-face mask made of bronze, in the vein of Roman cavalry masks. Provides decent protection and gives an imposing post-apocalyptic look.", + "weight": "950 g", + "price": "500 USD", + "material": [ "bronze" ], + "color": "yellow" + }, { "id": "mask_dust", "repairs_like": "tshirt", diff --git a/data/json/recipes/armor/arms.json b/data/json/recipes/armor/arms.json index 6984c45620fe..566bacac1231 100644 --- a/data/json/recipes/armor/arms.json +++ b/data/json/recipes/armor/arms.json @@ -102,6 +102,19 @@ "qualities": [ { "id": "HAMMER", "level": 2 }, { "id": "SAW_M", "level": 1 } ], "components": [ [ [ "sheet_metal_small", 4 ] ] ] }, + { + "result": "armguard_bronze", + "type": "recipe", + "category": "CC_ARMOR", + "subcategory": "CSC_ARMOR_ARMS", + "skill_used": "fabrication", + "difficulty": 4, + "time": "30 m", + "autolearn": true, + "book_learn": [ [ "textbook_armwest", 3 ], [ "recipe_melee", 3 ] ], + "using": [ [ "forging_standard", 4 ], [ "bronzesmithing_tools", 1 ] ], + "components": [ [ [ "fabric_standard", 1, "LIST" ], [ "fabric_hides_any", 1, "LIST" ] ], [ [ "scrap_bronze", 7 ] ] ] + }, { "result": "armguard_paper", "type": "recipe", diff --git a/data/json/recipes/armor/head.json b/data/json/recipes/armor/head.json index d00e212542ce..00a0489736fd 100644 --- a/data/json/recipes/armor/head.json +++ b/data/json/recipes/armor/head.json @@ -83,6 +83,19 @@ ], "flags": [ "BLIND_EASY", "NO_RESIZE" ] }, + { + "result": "cap_arming", + "type": "recipe", + "category": "CC_ARMOR", + "subcategory": "CSC_ARMOR_HEAD", + "skill_used": "tailor", + "difficulty": 4, + "time": "25 m", + "autolearn": true, + "book_learn": [ [ "textbook_armwest", 3 ] ], + "using": [ [ "sewing_standard", 10 ] ], + "components": [ [ [ "rag", 10 ] ] ] + }, { "result": "cowboy_hat", "type": "recipe", @@ -1490,6 +1503,32 @@ "tools": [ [ [ "crucible", -1 ], [ "crucible_clay", -1 ] ] ], "components": [ [ [ "goggles_welding", 1 ] ] ] }, + { + "result": "mask_cavalry_iron", + "type": "recipe", + "category": "CC_ARMOR", + "subcategory": "CSC_ARMOR_HEAD", + "skill_used": "fabrication", + "difficulty": 4, + "time": "4 h", + "autolearn": true, + "book_learn": [ [ "textbook_armwest", 3 ], [ "textbook_armeast", 3 ] ], + "using": [ [ "blacksmithing_intermediate", 8 ], [ "steel_standard", 2 ] ], + "tools": [ [ [ "crucible", -1 ], [ "crucible_clay", -1 ] ] ], + "components": [ [ [ "fabric_standard", 1, "LIST" ], [ "fabric_hides_any", 1, "LIST" ] ] ] + }, + { + "result": "mask_cavalry_bronze", + "type": "recipe", + "category": "CC_ARMOR", + "subcategory": "CSC_ARMOR_HEAD", + "skill_used": "fabrication", + "difficulty": 5, + "time": "45 m", + "book_learn": [ [ "textbook_armwest", 3 ], [ "textbook_armeast", 3 ] ], + "using": [ [ "forging_standard", 2 ], [ "bronzesmithing_tools", 1 ] ], + "components": [ [ [ "scrap_bronze", 5 ] ], [ [ "fabric_standard", 1, "LIST" ], [ "fabric_hides_any", 1, "LIST" ] ] ] + }, { "result": "wetsuit_hood", "type": "recipe", From 2a535c013189af15afd997edcf1b0965bdab3cbd Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 24 Sep 2023 11:05:25 +0900 Subject: [PATCH 05/28] feat: simplify friendly swap and pushing (#3232) * refactor: remove swap action it was already handled much intuitively (just walk into it) via `game::place_player` * feat: pushing friendly monster always succeeds - it was weird when you have same chance to fail pusing your cat or zombie hulk - also they're friendly, so no problem with that --- src/monexamine.cpp | 47 +++------------------------------------------- src/monexamine.h | 1 - 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/src/monexamine.cpp b/src/monexamine.cpp index 8a65166e39a8..e4898741fc10 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -67,8 +67,7 @@ static const species_id ZOMBIE( "ZOMBIE" ); bool monexamine::pet_menu( monster &z ) { enum choices { - swap_pos = 0, - push_zlave, + push_zlave = 0, lead, stop_lead, rename, @@ -110,7 +109,6 @@ bool monexamine::pet_menu( monster &z ) amenu.text = string_format( _( "What to do with your %s?" ), pet_name ); - amenu.addentry( swap_pos, true, 's', _( "Swap positions" ) ); amenu.addentry( push_zlave, true, 'p', _( "Push %s" ), pet_name ); if( z.has_effect( effect_leashed ) ) { if( z.has_effect( effect_led_by_leash ) ) { @@ -252,9 +250,6 @@ bool monexamine::pet_menu( monster &z ) int choice = amenu.ret; switch( choice ) { - case swap_pos: - swap( z ); - break; case push_zlave: push( z ); break; @@ -507,8 +502,7 @@ bool monexamine::pay_bot( monster &z ) bool monexamine::mfriend_menu( monster &z ) { enum choices { - swap_pos = 0, - push_monster, + push_monster = 0, rename, attack }; @@ -518,7 +512,6 @@ bool monexamine::mfriend_menu( monster &z ) amenu.text = string_format( _( "What to do with your %s?" ), pet_name ); - amenu.addentry( swap_pos, true, 's', _( "Swap positions" ) ); amenu.addentry( push_monster, true, 'p', _( "Push %s" ), pet_name ); amenu.addentry( rename, true, 'e', _( "Rename" ) ); amenu.addentry( attack, true, 'a', _( "Attack" ) ); @@ -527,9 +520,6 @@ bool monexamine::mfriend_menu( monster &z ) const int choice = amenu.ret; switch( choice ) { - case swap_pos: - swap( z ); - break; case push_monster: push( z ); break; @@ -587,44 +577,13 @@ void monexamine::mount_pet( monster &z ) get_avatar().mount_creature( z ); } -void monexamine::swap( monster &z ) -{ - std::string pet_name = z.get_name(); - avatar &you = get_avatar(); - you.moves -= 150; - - ///\EFFECT_STR increases chance to successfully swap positions with your pet - ///\EFFECT_DEX increases chance to successfully swap positions with your pet - if( !one_in( ( you.str_cur + you.dex_cur ) / 6 ) ) { - bool t = z.has_effect( effect_tied ); - if( t ) { - z.remove_effect( effect_tied ); - } - - g->swap_critters( you, z ); - - if( t ) { - z.add_effect( effect_tied, 1_turns, num_bp ); - } - add_msg( _( "You swap positions with your %s." ), pet_name ); - } else { - add_msg( _( "You fail to budge your %s!" ), pet_name ); - } -} - void monexamine::push( monster &z ) { std::string pet_name = z.get_name(); avatar &you = get_avatar(); you.moves -= 30; - ///\EFFECT_STR increases chance to successfully push your pet - if( !one_in( you.str_cur ) ) { - add_msg( _( "You pushed the %s." ), pet_name ); - } else { - add_msg( _( "You pushed the %s, but it resisted." ), pet_name ); - return; - } + add_msg( _( "You pushed the %s." ), pet_name ); point delta( z.posx() - you.posx(), z.posy() - you.posy() ); z.move_to( tripoint( z.posx() + delta.x, z.posy() + delta.y, z.posz() ) ); diff --git a/src/monexamine.h b/src/monexamine.h index fa0ba71c6e3f..1b923b2a7e5b 100644 --- a/src/monexamine.h +++ b/src/monexamine.h @@ -12,7 +12,6 @@ bool pay_bot( monster &z ); bool mfriend_menu( monster &z ); void remove_battery( monster &z ); void insert_battery( monster &z ); -void swap( monster &z ); void push( monster &z ); void rename_pet( monster &z ); void attach_bag_to( monster &z ); From fd9e894426422bda98f11e3a37d34324a81440c4 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sun, 24 Sep 2023 00:20:35 -0500 Subject: [PATCH 06/28] Give No Hope the e (#3246) --- data/mods/No_Hope/Mapgen/parking_garage.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/mods/No_Hope/Mapgen/parking_garage.json b/data/mods/No_Hope/Mapgen/parking_garage.json index 547cb79ef6e8..257f32ade945 100644 --- a/data/mods/No_Hope/Mapgen/parking_garage.json +++ b/data/mods/No_Hope/Mapgen/parking_garage.json @@ -39,7 +39,9 @@ "#": "t_rock", "*": "t_open_air", "E": "t_elevator", + "e": "t_elevator_control", "x": "t_console_broken", + "X": "t_gates_control_concrete", "@": "t_generator_broken", "&": "t_machinery_heavy" }, From 855e278c44260a932018e752760b77801de7df20 Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 24 Sep 2023 14:55:18 +0900 Subject: [PATCH 07/28] fix: allow elevator misalignment (#3181) * fix: elevator misalignment in sarcophagus * fix: apartments_mod stair alignment * fix: make finding elevators more forgiving * refactor: move `and_then` to `cata_algo.h` _rust itertools interop when_ see: https://github.com/cataclysmbnteam/Cataclysm-BN/pull/3181#discussion_r1331933368 Co-authored-by: olanti-p --------- Co-authored-by: olanti-p --- data/json/mapgen/apartment_mod.json | 4 +- .../mapgen/hazardous_waste_sarcophagus.json | 8 ++-- src/cata_algo.h | 12 ++++++ src/iexamine_elevator.cpp | 38 ++++++++++++++++--- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/data/json/mapgen/apartment_mod.json b/data/json/mapgen/apartment_mod.json index 9ddd7673b380..b1144f5cf81a 100644 --- a/data/json/mapgen/apartment_mod.json +++ b/data/json/mapgen/apartment_mod.json @@ -16,10 +16,10 @@ " RsswFFFF...^|.STb| |bTS.|...FFFF.wssR ", " Rssw........+...b|-WW-|b...+........wssR ", " RssX........|--|-|....|-|--|........XssR ", - " Rss|1.htth...oo|Y|<...|Y|..........1|ssR ", + " Rss|1.htth...oo|Y|....|Y|..........1|ssR ", " Rss|e.htth.....+.|....|.+..........e|ssR ", " |-----|2.........A|-|-..-|-|..hh......u|-----| ", - " |..BBd|uO3........|........|..tt....3O2|dBB..| ", + " |..BBd|uO3........|<.......|..tt....3O2|dBB..| ", " w..BB.|--|+|......D........D..tt..|+|--|.BB..w ", " |d....+.r|u|^....t|........|..hh.^|u|r.+....d| ", " |r...||--|-|------|........|------|-|--||...r| ", diff --git a/data/json/mapgen/hazardous_waste_sarcophagus.json b/data/json/mapgen/hazardous_waste_sarcophagus.json index b315c1c11027..7e3e02d73605 100644 --- a/data/json/mapgen/hazardous_waste_sarcophagus.json +++ b/data/json/mapgen/hazardous_waste_sarcophagus.json @@ -35,11 +35,11 @@ " f ////////////////////+///LLLLLLL/// f ", " f /////////////////////.//6~~~~~~~./// f ", " f //.......................~~~~~~~~..// f ", - " f //.......||||............~~~~~~~~~..// f ", - " f //........|EE.......A....~~~~~~~~~~..// f ", + " f //.......................~~~~~~~~~..// f ", + " f //........||||......A....~~~~~~~~~~..// f ", " f //...S....|EE......AA...~~~~~~~~~~~.9// f ", - " f //...P....|e.|.....AA..~~~~~~~~~~~~.9// f ", - " f //.``P``...............~~~~~~~~~~~~.9// f ", + " f //...P....|EE......AA..~~~~~~~~~~~~.9// f ", + " f //.``P``..|e.|.........~~~~~~~~~~~~.9// f ", " f //.`$$$`.......AAA.....~~~~~~~~~~~~.9// f ", " f //.`$$$`6......AA......~~~~~~~~~~~~.9// f ", " f //.`$$$`...............~~~~~~~~~~~~..// f ", diff --git a/src/cata_algo.h b/src/cata_algo.h index 0bcf8c13a0e2..1a7a447ed9bc 100644 --- a/src/cata_algo.h +++ b/src/cata_algo.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -120,6 +121,17 @@ std::vector> find_cycles( const std::unordered_map +auto and_then( std::optional const &opt, Fn &&f ) -> std::optional> +{ + if( opt ) { + return std::optional{f( *opt )}; + } + return std::nullopt; +} + + } // namespace cata #endif // CATA_SRC_CATA_ALGO_H diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp index 0761ef5c71ce..27889bfe6b9e 100644 --- a/src/iexamine_elevator.cpp +++ b/src/iexamine_elevator.cpp @@ -1,3 +1,6 @@ +#include + +#include "cata_algo.h" #include "game.h" #include "iexamine.h" #include "mapdata.h" @@ -60,13 +63,27 @@ auto dest( const elevator::tiles &elevator_here, return tiles; } +/// allow using misaligned elevators. +/// doesn't prevent you being stuck in the wall tho cause i was lazy +auto find_elevators_nearby( const tripoint &pos ) -> std::optional +{ + constexpr int max_misalign = 3; + map &here = get_map(); + + for( const auto &p : closest_points_first( pos, max_misalign ) ) { + if( here.has_flag( TFLAG_ELEVATOR, p ) ) { + return p; + } + } + return {}; +} + auto choose_floor( const tripoint &examp, const tripoint_abs_omt &this_omt, const tripoint &sm_orig ) -> int { constexpr int retval_offset = 10000; // workaround for uilist retval autoassign when retval == -1 const auto this_floor = _( " (this floor)" ); - map &here = get_map(); uilist choice; choice.title = _( "Please select destination floor" ); for( int z = OVERMAP_HEIGHT; z >= -OVERMAP_DEPTH; z-- ) { @@ -75,7 +92,7 @@ auto choose_floor( const tripoint &examp, const tripoint_abs_omt &this_omt, const tripoint zp = rotate_point_sm( { examp.xy(), z }, sm_orig, turns ); - if( here.ter( zp )->examine != &iexamine::elevator ) { + if( !find_elevators_nearby( zp ) ) { continue; } const std::string omt_name = overmap_buffer.ter_existing( that_omt )->get_name(); @@ -199,6 +216,19 @@ auto move_vehicles( const elevator_vehicles &vehs, const tripoint &sm_orig, int here.reset_vehicle_cache(); } +auto move_player( player &p, const int movez, tripoint_abs_ms old_abs_pos ) -> void +{ + map &here = get_map(); + + g->vertical_shift( movez ); + // yes, this is inefficient, but i'm lazy + cata::and_then( elevator::find_elevators_nearby( p.pos() ), []( const tripoint & pos ) { + return g->place_player( pos ); + } ); + + cata_event_dispatch::avatar_moves( *p.as_avatar(), here, old_abs_pos.raw() ); +} + } //namespace elevator } // namespace @@ -234,7 +264,5 @@ void iexamine::elevator( player &p, const tripoint &examp ) elevator::move_items( elevator_here, elevator_dest ); elevator::move_creatures( elevator_here, elevator_dest ); elevator::move_vehicles( vehs, sm_orig, movez, turns ); - - g->vertical_shift( movez ); - cata_event_dispatch::avatar_moves( *p.as_avatar(), here, old_abs_pos.raw() ); + elevator::move_player( p, movez, old_abs_pos ); } From ce86805b8cf8b1a686c4b861de5c01610061f4c4 Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 24 Sep 2023 14:56:12 +0900 Subject: [PATCH 08/28] ci: remove unused workflow files (#3245) - astyle: obsoleted by autofix.yml - json: obsoleted by autofix.yml - doxygen: obsoleted by documentation.yml --- .github/workflows/astyle.yml | 42 -------------------------------- .github/workflows/doxygen.yml | 45 ----------------------------------- .github/workflows/json.yml | 35 --------------------------- 3 files changed, 122 deletions(-) delete mode 100644 .github/workflows/astyle.yml delete mode 100644 .github/workflows/doxygen.yml delete mode 100644 .github/workflows/json.yml diff --git a/.github/workflows/astyle.yml b/.github/workflows/astyle.yml deleted file mode 100644 index 58c19e4fa569..000000000000 --- a/.github/workflows/astyle.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: astyle - -on: - pull_request_target: - paths: [".github/workflows/astyle.yml", "Makefile", ".astylerc", "**.cpp", "**.h", "**.c"] - -jobs: - skip-duplicates: - continue-on-error: true - runs-on: ubuntu-22.04 - # Map a step output to a job output - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@master - with: - cancel_others: "true" - paths: '[".github/workflows/astyle.yml", "Makefile", ".astylerc", "**.cpp", "**.h", "**.c"]' - astyle-code: - name: astyle check - needs: skip-duplicates - if: ${{ needs.skip-duplicates.outputs.should_skip != 'true' }} - - runs-on: ubuntu-22.04 - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - - name: install dependencies - run: sudo apt-get install astyle - - - name: astyle check - run: make astyle-check - - - name: Display Corrections - if: failure() - run: | - make astyle - git diff diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml deleted file mode 100644 index b3973671dc49..000000000000 --- a/.github/workflows/doxygen.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Generate Documentation - -permissions: - contents: write - -on: - push: - branches: [upload] - workflow_dispatch: - -concurrency: - group: documentation - cancel-in-progress: true - -jobs: - documentation: - runs-on: ubuntu-22.04 - - steps: - - name: checkout repository - uses: actions/checkout@v3 - - - name: cache css - id: cache-css - uses: actions/cache@v3 - with: - key: doxygen-css-cache - path: ./doxygen_doc/doxygen-awesome-css - - - if: ${{ steps.cache-css.outputs.cache-hit != 'true' }} - name: download css - run: | - git clone https://github.com/jothepro/doxygen-awesome-css ./doxygen_doc/doxygen-awesome-css - - name: run doxygen - uses: mattnotmitt/doxygen-action@v1.9.2 - with: - working-directory: . - doxyfile-path: ./doxygen_doc/Doxyfile - # additional-packages: font-fira-code - - - name: deploy - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./doxygen_doc/html/ diff --git a/.github/workflows/json.yml b/.github/workflows/json.yml deleted file mode 100644 index 117372d77af8..000000000000 --- a/.github/workflows/json.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: JSON Validation - -on: - pull_request: - paths: ["**.json"] - -jobs: - skip-duplicates: - continue-on-error: true - runs-on: ubuntu-22.04 - # Map a step output to a job output - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@master - with: - cancel_others: "true" - paths: '["**.json", ".github/workflows/json.yml"]' - style-json: - name: JSON style check - - runs-on: ubuntu-22.04 - needs: skip-duplicates - if: ${{ needs.skip-duplicates.outputs.should_skip != 'true' }} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - name: JSON style check - run: make style-all-json-parallel COMPILER=g++-11 RELEASE=1 - - name: Display Corrections - if: failure() - run: git diff From b09decc61316dba7d9042624e44973ef1aa5ed54 Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 24 Sep 2023 14:56:30 +0900 Subject: [PATCH 09/28] build: remove chkjson (#3247) - BN discord had 3 mentions of chkjson in recorded history and all of them was by me - cataclysm executable already provides same functionality via `--check-mods` --- .gitignore | 2 - CMakeLists.txt | 4 +- Makefile | 12 --- build-scripts/build.sh | 3 - src/chkjson/CMakeLists.txt | 24 ----- src/chkjson/chkjson.cpp | 173 ------------------------------------- 6 files changed, 1 insertion(+), 217 deletions(-) delete mode 100644 src/chkjson/CMakeLists.txt delete mode 100644 src/chkjson/chkjson.cpp diff --git a/.gitignore b/.gitignore index 9633f8a158f6..734b36c2e162 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -!src/chkjson *.7z *.a *.d @@ -41,7 +40,6 @@ cataclysm-tiles cataclysm-tiles.exe.manifest cataclysm-vcpkg cataclysmdda-* -chkjson* debug.log logg.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index c38a126a9d33..700800055b7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,9 +390,7 @@ endif () add_subdirectory(src) add_subdirectory(data) add_subdirectory(lang) -if (NOT MSVC) - add_subdirectory(src/chkjson) -endif () + add_subdirectory(tests) if (JSON_FORMAT) add_subdirectory(tools/format) diff --git a/Makefile b/Makefile index 4a1bf0ec72bb..14f76f4dd1f7 100644 --- a/Makefile +++ b/Makefile @@ -163,7 +163,6 @@ else endif W32TILESTARGET = $(BUILD_PREFIX)$(TILES_TARGET_NAME).exe W32TARGET = $(BUILD_PREFIX)$(TARGET_NAME).exe -CHKJSON_BIN = $(BUILD_PREFIX)chkjson BINDIST_DIR = $(BUILD_PREFIX)bindist BUILD_DIR = $(CURDIR) SRC_DIR = src @@ -578,7 +577,6 @@ endif # Global settings for Windows targets ifeq ($(TARGETSYSTEM),WINDOWS) - CHKJSON_BIN = chkjson.exe TARGET = $(W32TARGET) BINDIST = $(W32BINDIST) BINDIST_CMD = $(W32BINDIST_CMD) @@ -802,7 +800,6 @@ HEADERS := $(wildcard $(SRC_DIR)/*.h) TESTSRC := $(wildcard tests/*.cpp) TESTHDR := $(wildcard tests/*.h) JSON_FORMATTER_SOURCES := tools/format/format.cpp src/json.cpp -CHKJSON_SOURCES := src/chkjson/chkjson.cpp src/json.cpp LUA_SOURCES := $(wildcard $(LUA_SRC_DIR)/*.c) CLANG_TIDY_PLUGIN_SOURCES := \ $(wildcard tools/clang-tidy-plugin/*.cpp tools/clang-tidy-plugin/*/*.cpp) @@ -814,7 +811,6 @@ ASTYLE_SOURCES := $(sort \ $(TESTSRC) \ $(TESTHDR) \ $(JSON_FORMATTER_SOURCES) \ - $(CHKJSON_SOURCES) \ $(CLANG_TIDY_PLUGIN_SOURCES) \ $(TOOLHDR)) @@ -961,19 +957,12 @@ src/version.cpp: src/version.h localization: lang/compile_mo.sh $(LANGUAGES) -$(CHKJSON_BIN): $(CHKJSON_SOURCES) - $(CXX) $(CXXFLAGS) $(TOOL_CXXFLAGS) -Isrc/chkjson -Isrc $(CHKJSON_SOURCES) -o $(CHKJSON_BIN) - -json-check: $(CHKJSON_BIN) - ./$(CHKJSON_BIN) - clean: clean-tests rm -rf *$(TARGET_NAME) *$(TILES_TARGET_NAME) rm -rf *$(TILES_TARGET_NAME).exe *$(TARGET_NAME).exe *$(TARGET_NAME).a rm -rf *obj *objwin rm -rf *$(BINDIST_DIR) *cataclysmbn-*.tar.gz *cataclysmbn-*.zip rm -f $(SRC_DIR)/version.h - rm -f $(CHKJSON_BIN) rm -f pch/*pch.hpp.gch rm -f pch/*pch.hpp.pch rm -f pch/*pch.hpp.d @@ -1222,7 +1211,6 @@ cmake-format: ./CMakeLists.txt \ ./data/CMakeLists.txt \ ./lang/CMakeLists.txt \ - ./src/chkjson/CMakeLists.txt \ ./src/CMakeLists.txt \ ./src/version.cmake \ ./tests/CMakeLists.txt \ diff --git a/build-scripts/build.sh b/build-scripts/build.sh index 20b89748c375..fbf51ab4f924 100755 --- a/build-scripts/build.sh +++ b/build-scripts/build.sh @@ -24,9 +24,6 @@ then make style-all-json-parallel RELEASE=1 tools/dialogue_validator.py data/json/npcs/* data/json/npcs/*/* data/json/npcs/*/*/* - # Also build chkjson (even though we're not using it), to catch any - # compile errors there - make -j "$num_jobs" chkjson elif [ -n "$JUST_JSON" ] then echo "Early exit on just-json change" diff --git a/src/chkjson/CMakeLists.txt b/src/chkjson/CMakeLists.txt deleted file mode 100644 index 198d403d26b2..000000000000 --- a/src/chkjson/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# JSON check utility -cmake_minimum_required(VERSION 3.16) - -set(CHKJSON_SOURCES ${CMAKE_SOURCE_DIR}/src/json.cpp ${CMAKE_SOURCE_DIR}/src/chkjson/chkjson.cpp) - -set(CHKJSON_HEADERS ${CMAKE_SOURCE_DIR}/src/json.h) - -# test chain -add_custom_target(check_json WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - -add_custom_command( - TARGET check_json - PRE_BUILD - COMMAND chkjson - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - -include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/chkjson) - -# Add the actual executable -if (WIN32) - add_executable(chkjson WIN32 EXCLUDE_FROM_ALL ${CHKJSON_SOURCES} ${CHKJSON_HEADERS}) -else () - add_executable(chkjson EXCLUDE_FROM_ALL ${CHKJSON_SOURCES} ${CHKJSON_HEADERS}) -endif () diff --git a/src/chkjson/chkjson.cpp b/src/chkjson/chkjson.cpp deleted file mode 100644 index 46d08471de32..000000000000 --- a/src/chkjson/chkjson.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* Main Loop for cataclysm - * Linux only I guess - * But maybe not - * Who knows - */ -#include -#include -#include -#include -#include // for strcmp -#include // for stack (obviously) -#include -#include -#include -#include // for throwing errors -#include -#include -#include - -#include "json.h" - -// copypasta: file_finder.cpp -static std::vector get_files_from_path( std::string extension, std::string root_path, - bool recursive_search, bool match_extension ) -{ - std::vector files; - const size_t extsz = extension.size(); - const char *c_extension = extension.c_str(); - // test for empty root path - if( root_path.empty() ) { - root_path = "."; - } - - std::stack directories, tempstack; - directories.push( root_path ); - std::string path; - - while( !directories.empty() ) { - path = directories.top(); - directories.pop(); - - DIR *root = opendir( path.c_str() ); - - if( root ) { - struct dirent *root_file; - struct stat _buff; - DIR *subdir; - - while( ( root_file = readdir( root ) ) ) { - // check to see if it is a folder! - if( stat( root_file->d_name, &_buff ) != 0x4 ) { - // ignore '.' and '..' folder names, which are current and parent folder relative paths - if( ( strcmp( root_file->d_name, "." ) != 0 ) && ( strcmp( root_file->d_name, ".." ) != 0 ) ) { - std::string subpath = path + "/" + root_file->d_name; - - if( recursive_search ) { - subdir = opendir( subpath.c_str() ); - if( subdir ) { - tempstack.push( subpath ); - closedir( subdir ); - } - } - } - } - // check to see if it is a file with the appropriate extension - std::string tmp = root_file->d_name; - if( tmp.find( c_extension, match_extension ? tmp.size() - extsz : 0 ) != std::string::npos ) { - std::string fullpath = path + "/" + tmp; - files.push_back( fullpath ); - } - } - closedir( root ); - } - // Directories are added to tempstack in A->Z order, which makes them pop from Z->A. This Makes sure that directories are - // searched in the proper order and that the final output is in the proper order. - while( !tempstack.empty() ) { - directories.push( tempstack.top() ); - tempstack.pop(); - } - } - return files; -} - -// copypasta: init.cpp -static void load_object( JsonObject &jo ) -{ - std::string type = jo.get_string( "type" ); - if( !jo.has_string( "type" ) ) { - jo.throw_error( "JSON object has no type" ); - } -} -static void load_all_from_json( JsonIn &jsin ) -{ - char ch; - jsin.eat_whitespace(); - // examine first non-whitespace char - ch = jsin.peek(); - if( ch == '{' ) { - // find type and dispatch single object - JsonObject jo = jsin.get_object(); - load_object( jo ); - jo.finish(); - // if there's anything else in the file, it's an error. - jsin.eat_whitespace(); - if( jsin.good() ) { - std::stringstream err; - err << "expected single-object file but found '"; - err << jsin.peek() << "'"; - jsin.error( err.str() ); - } - } else if( ch == '[' ) { - jsin.start_array(); - // find type and dispatch each object until array close - while( !jsin.end_array() ) { - jsin.eat_whitespace(); - ch = jsin.peek(); - if( ch != '{' ) { - std::stringstream err; - err << "expected array of objects but found '"; - err << ch << "', not '{'"; - jsin.error( err.str() ); - } - JsonObject jo = jsin.get_object(); - load_object( jo ); - jo.finish(); - } - } else { - // not an object or an array? - std::stringstream err; - err << "expected object or array, but found '" << ch << "'"; - jsin.error( err.str() ); - } -} - -static void load_json_dir( const std::string &dirname ) -{ - // get a list of all files in the directory - std::vector dir = - get_files_from_path( ".json", dirname, true, true ); - // iterate over each file - std::vector::iterator it; - for( it = dir.begin(); it != dir.end(); it++ ) { - // open the file as a stream - std::ifstream infile( it->c_str(), std::ifstream::in | std::ifstream::binary ); - // and stuff it into ram - std::istringstream iss( - std::string( - ( std::istreambuf_iterator( infile ) ), - std::istreambuf_iterator() - ) - ); - infile.close(); - // parse it - try { - JsonIn jsin( iss ); - load_all_from_json( jsin ); - } catch( const JsonError &err ) { - throw std::runtime_error( *( it ) + ": " + err.what() ); - } - } -} - -int main( int, char ** ) -{ - setlocale( LC_ALL, "" ); - try { - load_json_dir( "data/json" ); - } catch( const std::exception &err ) { - printf( "Error: %s\n", err.what() ); - return 1; - } - return 0; -} From dc6b486bfa25e99f41834077d1dd64d914a293bc Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Sun, 24 Sep 2023 01:00:00 -0500 Subject: [PATCH 10/28] UDP External Tileset Update (#3244) --- .../external_tileset/External Tileset Info.md | 6 ++++++ .../External_Tileset_DP_Normal.json | 12 +++++++++++- .../External_Tileset_DP_Normal.png | Bin 37138 -> 42528 bytes data/json/items/armor/arms_armor.json | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/data/json/external_tileset/External Tileset Info.md b/data/json/external_tileset/External Tileset Info.md index 810dac26b248..4c3315ecd0b6 100644 --- a/data/json/external_tileset/External Tileset Info.md +++ b/data/json/external_tileset/External Tileset Info.md @@ -15,6 +15,8 @@ Links to relevant pull requests, for content covered below: - Utility light can be switched off: [#1003](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1003) - Mi-go nerve cluster: [#1962](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1962) - Scaled bear: [#1371](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1371) +- Buckler and welded shield: [#2878](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2878) +- Battle masks and bronze arm guards: [#3221](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/3221) ## Undead People @@ -39,6 +41,10 @@ The following is a current list of sprites this folder adds to the UDP tileset, * New worn sprite for `compgreatbow`, as compound greatbow in DDA can't be worn thus UDP lacks a worn sprite for it (which we'd liklely need to edit to resemble composite bow anyway). * Katar, including sprite for wielded state. Item specific to BN. * Sai (weapon, not to be confused with telecoms location), including sprite for wielded state. Item specific to BN. +* Welded shield, including worn and wielded. Item specific to BN. +* Buckler, including worn and wielded. Item specific to BN. +* Battle masks, iron and bronze, including worn sprites. Items specific to BN. +* Bronze arm guards, including worn sprites. Item specific to BN. ### External_Tileset_DP_Large.png diff --git a/data/json/external_tileset/External_Tileset_DP_Normal.json b/data/json/external_tileset/External_Tileset_DP_Normal.json index d33b7f1a4d83..a932acac835c 100644 --- a/data/json/external_tileset/External_Tileset_DP_Normal.json +++ b/data/json/external_tileset/External_Tileset_DP_Normal.json @@ -43,7 +43,17 @@ "fg": [ { "weight": 10, "sprite": 32 }, { "weight": 10, "sprite": 33 }, { "weight": 10, "sprite": 34 } ], "animated": false }, - { "id": "corpse_mon_feral_human_chainsaw", "fg": 35 } + { "id": "corpse_mon_feral_human_chainsaw", "fg": 35 }, + { "id": "shield_welded", "fg": 36 }, + { "id": [ "overlay_worn_shield_welded", "overlay_wielded_shield_welded" ], "fg": 37 }, + { "id": "shield_buckler", "fg": 38 }, + { "id": [ "overlay_worn_shield_buckler", "overlay_wielded_shield_buckler" ], "fg": 39 }, + { "id": "mask_cavalry_iron", "fg": 40 }, + { "id": "overlay_worn_mask_cavalry_iron", "fg": 41 }, + { "id": "mask_cavalry_bronze", "fg": 42 }, + { "id": "overlay_worn_mask_cavalry_bronze", "fg": 43 }, + { "id": "armguard_bronze", "fg": 44 }, + { "id": "overlay_worn_armguard_bronze", "fg": 45 } ], "sprite_width": 32, "sprite_height": 32 diff --git a/data/json/external_tileset/External_Tileset_DP_Normal.png b/data/json/external_tileset/External_Tileset_DP_Normal.png index b8e7bd3775703d510acaa08a5e6dad195f2d74d2..d48779b7fe4009cf2d515ecd3b6710231d7a6bc2 100644 GIT binary patch delta 21349 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%0AAV9z&D;<_L0}^=!kLAq!Fxb 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 delta 16084 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 VqQ2Gcbpd@sN=#m~Tv$Kg{{g{iW1|27 diff --git a/data/json/items/armor/arms_armor.json b/data/json/items/armor/arms_armor.json index 6a028c0fbf12..b9d6f8684888 100644 --- a/data/json/items/armor/arms_armor.json +++ b/data/json/items/armor/arms_armor.json @@ -145,7 +145,7 @@ "id": "armguard_bronze", "copy-from": "armguard_metal", "type": "ARMOR", - "name": { "str": "pair of bronze arm guards", "str_pl": "pairs of arm guards" }, + "name": { "str": "pair of bronze arm guards", "str_pl": "pairs of bronze arm guards" }, "description": "A pair of arm guards hammered out from sheets of bronze, for a classical take on the Post-Apocalyptic Warrior look.", "weight": "1500 g", "price": "400 USD", From 56d82120e1130cef99bc6020e25bcf18b5fd4299 Mon Sep 17 00:00:00 2001 From: Vollch Date: Sun, 24 Sep 2023 13:05:02 +0300 Subject: [PATCH 11/28] Proper river shores under bridges (#3212) --- data/json/mapgen/bridges.json | 150 +++++++++--------- .../overmap_terrain_river.json | 6 + .../overmap_terrain_transportation.json | 3 +- src/mapgen_functions.cpp | 57 ++++++- src/mapgen_functions.h | 1 + 5 files changed, 139 insertions(+), 78 deletions(-) diff --git a/data/json/mapgen/bridges.json b/data/json/mapgen/bridges.json index 677887ecc64f..df467a352fe7 100644 --- a/data/json/mapgen/bridges.json +++ b/data/json/mapgen/bridges.json @@ -48,32 +48,32 @@ "method": "json", "om_terrain": [ "bridge_under" ], "object": { - "fill_ter": "t_water_moving_dp", + "predecessor_mapgen": "river_shore", "rows": [ - "~~~~~~~~s######s~~~~~~~~", - "~~~~~~~~ss####ss~~~~~~~~", - "~~~~~~~~~ss##ss~~~~~~~~~", - "~~~~~~~~~~ssss~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~~~~~~~~~~~~~~~", - "~~~~~~~~~~ssss~~~~~~~~~~", - "~~~~~~~~~ss##ss~~~~~~~~~", - "~~~~~~~~ss####ss~~~~~~~~", - "~~~~~~~~s######s~~~~~~~~" + " s######s ", + " ss####ss ", + " ss##ss ", + " ssss ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ssss ", + " ss##ss ", + " ss####ss ", + " s######s " ], "palettes": [ "bridge_ground_palette" ] } @@ -124,32 +124,32 @@ "//": "Legacy bridge that blocks river", "om_terrain": [ "bridge" ], "object": { - "fill_ter": "t_water_moving_dp", + "predecessor_mapgen": "river_shore", "rows": [ - "~~=_................_=~~", - "~~=_.......::......._=~~", - "~~=_.......::...v..._=~~", - "~~=_.......::......._=~~", - "~~=_...^............_=~~", - "~~=_.......::......._=~~", - "~~=_.......::......._=~~", - "~~=_.......::......._=~~", - "~~=_............v..._=~~", - "~~=_.......::......._=~~", - "~~=_.....^.::......._=~~", - "~~=_.......::......._=~~", - "~~=_................_=~~", - "~~=_.......::..v...._=~~", - "~~=_.......::......._=~~", - "~~=_..^....::......._=~~", - "~~=_................_=~~", - "~~=_.......::......._=~~", - "~~=_.......::....v.._=~~", - "~~=_.......::......._=~~", - "~~=_................_=~~", - "~~=_....^..::......._=~~", - "~~=_.......::......._=~~", - "~~=_.......::......._=~~" + " =_................_= ", + " =_.......::......._= ", + " =_.......::...v..._= ", + " =_.......::......._= ", + " =_...^............_= ", + " =_.......::......._= ", + " =_.......::......._= ", + " =_.......::......._= ", + " =_............v..._= ", + " =_.......::......._= ", + " =_.....^.::......._= ", + " =_.......::......._= ", + " =_................_= ", + " =_.......::..v...._= ", + " =_.......::......._= ", + " =_..^....::......._= ", + " =_................_= ", + " =_.......::......._= ", + " =_.......::....v.._= ", + " =_.......::......._= ", + " =_................_= ", + " =_....^..::......._= ", + " =_.......::......._= ", + " =_.......::......._= " ], "palettes": [ "bridge_ground_palette" ], "items": { "_": { "item": "road", "chance": 1 } }, @@ -164,32 +164,32 @@ "method": "json", "om_terrain": [ "bridgehead_ground" ], "object": { - "fill_ter": "t_water_moving_dp", + "predecessor_mapgen": "river_shore", "rows": [ - "ss=_................_=ss", - "ss=_.......::......._=ss", - "ss=_.......::......._=ss", - "ss=_.......::......._=ss", - "ss=_................_=ss", - "ss=wuuuuuuuuuuuuuuuuw=ss", - "ss=ter_set( point( x, y ), grass_or_dirt() ); - } - if( circle_edge == 9 && one_in( 25 ) ) { + } else if( circle_edge == 9 && one_in( 25 ) ) { m->ter_set( point( x, y ), clay_or_sand() ); } else if( circle_edge <= 36 ) { m->ter_set( point( x, y ), t_water_moving_sh ); @@ -1780,6 +1780,59 @@ void mapgen_river_curved( mapgendata &dat ) } } +void mapgen_river_shore( mapgendata &dat ) +{ + map *const m = &dat.m; + fill_background( m, t_water_moving_dp ); + + bool ground_neswx[8] = {}; + // N E S W NE SE SW NW + for( int dir = 0; dir < 8; dir++ ) { + ground_neswx[dir] = !( dat.t_nesw[dir]->is_river() || + dat.t_nesw[dir]->is_lake() || + dat.t_nesw[dir]->is_lake_shore() ); + } + + // Draw shores on sides + for( int dir = 0; dir < 4; dir++ ) { + if( ground_neswx[dir] ) { + m->rotate( 4 - dir ); + for( int x = 0; x < SEEX * 2; x++ ) { + int ground_edge = rng( 1, 3 ); + int shallow_edge = rng( 4, 6 ); + line( m, grass_or_dirt(), point( x, 0 ), point( x, ground_edge ) ); + if( one_in( 25 ) ) { + m->ter_set( point( x, ++ground_edge ), clay_or_sand() ); + } + line( m, t_water_moving_sh, point( x, ++ground_edge ), point( x, shallow_edge ) ); + } + m->rotate( dir ); + } + } + + // Bite corner, unless there's a shore already + for( int dir = 0; dir < 4; dir++ ) { + if( ground_neswx[dir + 4] && !ground_neswx[dir] && !ground_neswx[( dir + 1 ) % 4] ) { + m->rotate( 4 - dir ); + int north_edge = rng( 16, 18 ); + int east_edge = rng( 4, 8 ); + for( int x = north_edge; x < SEEX * 2; x++ ) { + for( int y = 0; y < east_edge; y++ ) { + int circle_edge = ( ( SEEX * 2 - x ) * ( SEEX * 2 - x ) ) + ( y * y ); + if( circle_edge <= 8 ) { + m->ter_set( point( x, y ), grass_or_dirt() ); + } else if( circle_edge == 9 && one_in( 25 ) ) { + m->ter_set( point( x, y ), clay_or_sand() ); + } else if( circle_edge <= 36 ) { + m->ter_set( point( x, y ), t_water_moving_sh ); + } + } + } + m->rotate( dir ); + } + } +} + void mapgen_parking_lot( mapgendata &dat ) { map *const m = &dat.m; diff --git a/src/mapgen_functions.h b/src/mapgen_functions.h index bddf49d16287..7f7795a2851e 100644 --- a/src/mapgen_functions.h +++ b/src/mapgen_functions.h @@ -53,6 +53,7 @@ void mapgen_highway( mapgendata &dat ); void mapgen_river_curved_not( mapgendata &dat ); void mapgen_river_straight( mapgendata &dat ); void mapgen_river_curved( mapgendata &dat ); +void mapgen_river_shore( mapgendata &dat ); void mapgen_parking_lot( mapgendata &dat ); void mapgen_cave( mapgendata &dat ); void mapgen_cave_rat( mapgendata &dat ); From b545f49e93df7f4a42191c9512958f84b1ca32dc Mon Sep 17 00:00:00 2001 From: Vollch Date: Sun, 24 Sep 2023 13:57:44 +0300 Subject: [PATCH 12/28] Fixed some issues with bridge/road generation on overmap edge (#3203) --- src/overmap.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/overmap.cpp b/src/overmap.cpp index 230dc1d7d375..f378958718b5 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -3764,12 +3764,29 @@ pf::directed_path overmap::lay_out_connection( } } - const int dist = subtype->is_orthogonal() ? - manhattan_dist( dest, cur.pos ) : - trig_dist( dest, cur.pos ); - const int existency_mult = existing_connection ? 1 : 5; // Prefer existing connections. + if( prev && prev->dir == om_direction::type::invalid && cur.dir != om_direction::type::invalid ) { + // Non-linear connections starting near overmap border should always be perpendicular to that border + const oter_id &prev_id = ter( tripoint_om_omt( prev->pos, z ) ); + + if( !connection.can_start_at( prev_id ) && !inbounds( cur.pos, 1 ) && + inbounds( prev->pos + om_direction::displace( om_direction::opposite( cur.dir ), 1 ) ) ) { + return pf::node_score::rejected; + } + } + + int score = subtype->is_orthogonal() ? + manhattan_dist( dest, cur.pos ) : + trig_dist( dest, cur.pos ); + if( !existing_connection ) { + // Prefer existing connections + score *= 5; + } + if( !inbounds( cur.pos, 1 ) ) { + // Roads running next to overmap edge often looks unnatural and weird, better avoid them + score *= 2; + } - return pf::node_score( subtype->basic_cost, existency_mult * dist ); + return pf::node_score( subtype->basic_cost, score ); }; return pf::greedy_path( source, dest, point_om_omt( OMAPX, OMAPY ), estimate ); @@ -3935,6 +3952,8 @@ void overmap::build_connection( ter_set( pos, subtype->terrain->get_linear( new_line ) ); } else if( new_dir != om_direction::type::invalid ) { ter_set( pos, subtype->terrain->get_rotated( new_dir ) ); + } else if( prev_dir != om_direction::type::invalid ) { + ter_set( pos, subtype->terrain->get_rotated( prev_dir ) ); } prev_dir = new_dir; From d3c9a335f2fbbb7c5338457b6cd1d8f35ad0ea2a Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 01:00:54 +0900 Subject: [PATCH 13/28] docs: migrate external tilest info (#3249) --- .../external_tileset/External Tileset Info.md | 54 ------------- data/json/external_tileset/README.md | 1 + .../reference/graphics/external_tileset.md | 81 +++++++++++++++++++ 3 files changed, 82 insertions(+), 54 deletions(-) delete mode 100644 data/json/external_tileset/External Tileset Info.md create mode 120000 data/json/external_tileset/README.md create mode 100644 doc/src/content/docs/en/mod/json/reference/graphics/external_tileset.md diff --git a/data/json/external_tileset/External Tileset Info.md b/data/json/external_tileset/External Tileset Info.md deleted file mode 100644 index 4c3315ecd0b6..000000000000 --- a/data/json/external_tileset/External Tileset Info.md +++ /dev/null @@ -1,54 +0,0 @@ -# External Tileset Info -This folder is used for content specific to Bright Nights which are not presently in primary tilesets such as UDP or Ultica, for which `looks_like` is inadequate to depict the content to a satisfactory degree. It functions using the `mod_tileset` feature, applying any desired new sprites or overriding sprites to the specified tileset. - -The primary advantage of this method is to set aside sprites so they won't interfere with updating the tilesets themselves (as their sources are in the repositories of the tileset authors), and likewise ensuring anything specific to BN won't be accidentally erased, like it would if a tileset update was submitted to BN after these editing these sprites our versions of the tilesets. It also covers divergences in content were, by nessecity, a different sprite is a better fit. - -Links to relevant pull requests, for content covered below: -- Steam turbine: [#2815](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2815) -- Bullet animations: [#1861](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1681) -- Wooden shields, riot shields, and ballistic shields: [#2851](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2851) -- Lead sling bullet: [#2709](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2709) -- Leather and banded shields: [#2856](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2856) -- Edits to blueberry bushes, strawberry bushes, and cherry trees: [#2861](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2861) -- De-obsoleted wooden greatbow, reflavored compound/composite greatbow: [#2862](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2862) -- Katar and sai: [#2715](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2715) -- Utility light can be switched off: [#1003](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1003) -- Mi-go nerve cluster: [#1962](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1962) -- Scaled bear: [#1371](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1371) -- Buckler and welded shield: [#2878](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2878) -- Battle masks and bronze arm guards: [#3221](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/3221) - -## Undead People - -The following is a current list of sprites this folder adds to the UDP tileset, in which files and for what purpose. This is currently the only tileset with external_tileset coverage, but sprites for Ultica are planned for the future. - -### External_Tileset_DP_Normal.png - -* Furniture form of steam turbines, to be deconstructed for advanced steam engine. Content specific to BN. -* Animation effects for bullets in flight. Feature specific to BN. -* Wooden shield, including worn and wielded. Item specific to BN. -* Riot shield, including worn and wielded. Item specific to BN. -* Ballistic shield, including worn and wielded. Item specific to BN. -* Lead sling bullet. Item specific to BN, `looks_like` of `rock` did not seem fitting -* Leather-reinforced shield, including worn and wielded. Item specific to BN. -* Large leather-reinforced shield, including worn and wielded. Item specific to BN. -* Banded shield, including worn and wielded. Item specific to BN. -* Large banded shield, including worn and wielded. Item specific to BN. -* Swapped spring and summer sprites (the latter not depicting young berries) for blueberry bush, as harvest season has been moved in BN. -* Swapped spring and summer sprites (the latter not depicting young berries) for strawberry bush, as harvest season has been moved in BN. -* Fixed worn sprite for `woodgreatbow`, as it had a sprite error in its UDP version. `Note: this can be removed once UDP is updated in BN, as the fix has been published in the source repository.` -* Overriding sprite for `compgreatbow`, as its version in BN is modeled after a composite bow instead of a compound bow. -* New worn sprite for `compgreatbow`, as compound greatbow in DDA can't be worn thus UDP lacks a worn sprite for it (which we'd liklely need to edit to resemble composite bow anyway). -* Katar, including sprite for wielded state. Item specific to BN. -* Sai (weapon, not to be confused with telecoms location), including sprite for wielded state. Item specific to BN. -* Welded shield, including worn and wielded. Item specific to BN. -* Buckler, including worn and wielded. Item specific to BN. -* Battle masks, iron and bronze, including worn sprites. Items specific to BN. -* Bronze arm guards, including worn sprites. Item specific to BN. - -### External_Tileset_DP_Large.png - -* Off state for utility light. Ability to switch on and off specific to BN. -* Alien nerve cluster, furniture added to mi-go locations in BN. `Note: this can be removed once UDP is updated in BN, as the sprite for this has been published in the source repository.` -* Scaled bear, including corpse. Monster specific to BN. -* Cherry tree uses summer sprite (plus cherry blossom coloration), summer sprite depicted without berries, due to harvest season being moved in BN. diff --git a/data/json/external_tileset/README.md b/data/json/external_tileset/README.md new file mode 120000 index 000000000000..f3a135e640d7 --- /dev/null +++ b/data/json/external_tileset/README.md @@ -0,0 +1 @@ +../../../doc/src/content/docs/en/mod/json/reference/graphics/external_tileset.md \ No newline at end of file diff --git a/doc/src/content/docs/en/mod/json/reference/graphics/external_tileset.md b/doc/src/content/docs/en/mod/json/reference/graphics/external_tileset.md new file mode 100644 index 000000000000..17ee2f49578d --- /dev/null +++ b/doc/src/content/docs/en/mod/json/reference/graphics/external_tileset.md @@ -0,0 +1,81 @@ +--- +title: External Tilesets +--- + +`data/json/external_tileset` is used for content specific to Bright Nights which are not presently +in primary tilesets such as UDP or Ultica, for which `looks_like` is inadequate to depict the +content to a satisfactory degree. It functions using the `mod_tileset` feature, applying any desired +new sprites or overriding sprites to the specified tileset. + +The primary advantage of this method is to set aside sprites so they won't interfere with updating +the tilesets themselves (as their sources are in the repositories of the tileset authors), and +likewise ensuring anything specific to BN won't be accidentally erased, like it would if a tileset +update was submitted to BN after these editing these sprites our versions of the tilesets. It also +covers divergences in content were, by nessecity, a different sprite is a better fit. + +Links to relevant pull requests, for content covered below: + +- Steam turbine: [#2815](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2815) +- Bullet animations: [#1861](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1681) +- Wooden shields, riot shields, and ballistic shields: + [#2851](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2851) +- Lead sling bullet: [#2709](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2709) +- Leather and banded shields: [#2856](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2856) +- Edits to blueberry bushes, strawberry bushes, and cherry trees: + [#2861](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2861) +- De-obsoleted wooden greatbow, reflavored compound/composite greatbow: + [#2862](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2862) +- Katar and sai: [#2715](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2715) +- Utility light can be switched off: + [#1003](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1003) +- Mi-go nerve cluster: [#1962](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1962) +- Scaled bear: [#1371](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/1371) +- Buckler and welded shield: [#2878](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/2878) +- Battle masks and bronze arm guards: + [#3221](https://github.com/cataclysmbnteam/Cataclysm-BN/pull/3221) + +## Undead People + +The following is a current list of sprites this folder adds to the UDP tileset, in which files and +for what purpose. This is currently the only tileset with external_tileset coverage, but sprites for +Ultica are planned for the future. + +### External_Tileset_DP_Normal.png + +- Furniture form of steam turbines, to be deconstructed for advanced steam engine. Content specific + to BN. +- Animation effects for bullets in flight. Feature specific to BN. +- Wooden shield, including worn and wielded. Item specific to BN. +- Riot shield, including worn and wielded. Item specific to BN. +- Ballistic shield, including worn and wielded. Item specific to BN. +- Lead sling bullet. Item specific to BN, `looks_like` of `rock` did not seem fitting +- Leather-reinforced shield, including worn and wielded. Item specific to BN. +- Large leather-reinforced shield, including worn and wielded. Item specific to BN. +- Banded shield, including worn and wielded. Item specific to BN. +- Large banded shield, including worn and wielded. Item specific to BN. +- Swapped spring and summer sprites (the latter not depicting young berries) for blueberry bush, as + harvest season has been moved in BN. +- Swapped spring and summer sprites (the latter not depicting young berries) for strawberry bush, as + harvest season has been moved in BN. +- Fixed worn sprite for `woodgreatbow`, as it had a sprite error in its UDP version. + `Note: this can be removed once UDP is updated in BN, as the fix has been published in the source repository.` +- Overriding sprite for `compgreatbow`, as its version in BN is modeled after a composite bow + instead of a compound bow. +- New worn sprite for `compgreatbow`, as compound greatbow in DDA can't be worn thus UDP lacks a + worn sprite for it (which we'd liklely need to edit to resemble composite bow anyway). +- Katar, including sprite for wielded state. Item specific to BN. +- Sai (weapon, not to be confused with telecoms location), including sprite for wielded state. Item + specific to BN. +- Welded shield, including worn and wielded. Item specific to BN. +- Buckler, including worn and wielded. Item specific to BN. +- Battle masks, iron and bronze, including worn sprites. Items specific to BN. +- Bronze arm guards, including worn sprites. Item specific to BN. + +### External_Tileset_DP_Large.png + +- Off state for utility light. Ability to switch on and off specific to BN. +- Alien nerve cluster, furniture added to mi-go locations in BN. + `Note: this can be removed once UDP is updated in BN, as the sprite for this has been published in the source repository.` +- Scaled bear, including corpse. Monster specific to BN. +- Cherry tree uses summer sprite (plus cherry blossom coloration), summer sprite depicted without + berries, due to harvest season being moved in BN. From a5265911435234595120e6315a275d2b1e17718c Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 01:01:31 +0900 Subject: [PATCH 14/28] build(cmake): deduplicate library setup (#3248) * refactor: DRY library setup * fix: DOWNLOAD_EXTRACT_TIMESTAMP warning --- src/CMakeLists.txt | 89 ++------------------------ src/SetupLibrary.cmake | 47 ++++++++++++++ tools/clang-tidy-plugin/CMakeLists.txt | 5 ++ 3 files changed, 59 insertions(+), 82 deletions(-) create mode 100644 src/SetupLibrary.cmake diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index df0baa3901bb..e1f15113d78d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,8 @@ # Cataclysm BN client cmake_minimum_required(VERSION 3.16) +include(SetupLibrary.cmake) + 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) @@ -31,16 +33,10 @@ add_custom_command( ${CMAKE_SOURCE_DIR}/src/version.cmake WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + # Build tiles version if requested if (TILES) - add_library(cataclysm-tiles-common OBJECT ${CATACLYSM_BN_SOURCES} ${CATACLYSM_BN_HEADERS} - ${LUA_C_SOURCES}) - target_include_directories(cataclysm-tiles-common INTERFACE ${CMAKE_SOURCE_DIR}/src) - - if (USE_PCH_HEADER) - target_precompile_headers(cataclysm-tiles-common PRIVATE - ${CMAKE_SOURCE_DIR}/pch/main-pch.hpp) - endif () + setup_library(cataclysm-tiles-common) if (WIN32) add_definitions(-DUSE_WINMAIN) @@ -49,25 +45,9 @@ if (TILES) add_executable(cataclysm-tiles ${MAIN_CPP} ${MESSAGES_CPP}) endif () - if (LUA) - target_compile_definitions(cataclysm-tiles-common PUBLIC LUA) - target_include_directories(cataclysm-tiles-common PUBLIC ${CMAKE_SOURCE_DIR}/src) - target_include_directories(cataclysm-tiles-common PUBLIC ${CMAKE_SOURCE_DIR}/src/lua) - endif () - - add_dependencies(cataclysm-tiles-common get_version) - target_link_libraries(cataclysm-tiles cataclysm-tiles-common) target_compile_definitions(cataclysm-tiles-common PUBLIC TILES) - if (CMAKE_USE_PTHREADS_INIT) - target_compile_options(cataclysm-tiles-common PUBLIC "-pthread") - endif () - - if (CMAKE_THREAD_LIBS_INIT) - target_link_libraries(cataclysm-tiles-common ${CMAKE_THREAD_LIBS_INIT}) - endif () - if (NOT DYNAMIC_LINKING) # SDL, SDL_Image, SDL_ttf deps are required for static build target_include_directories( @@ -94,38 +74,15 @@ if (TILES) target_link_libraries(cataclysm-tiles-common ${SDL2_MIXER_LIBRARIES}) endif () - if (WIN32) - # Global settings for Windows targets (at end) - 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(cataclysm-tiles-common dbghelp.lib) - endif () - endif () - - if (LIBBACKTRACE) - target_link_libraries(cataclysm-tiles-common backtrace) - endif () - if (RELEASE) install(TARGETS cataclysm-tiles DESTINATION ${BIN_PREFIX}) endif () + endif () # Build curses version if requested if (CURSES) - add_library(cataclysm-common OBJECT ${CATACLYSM_BN_SOURCES} ${CATACLYSM_BN_HEADERS} - ${LUA_C_SOURCES}) - target_include_directories(cataclysm-common INTERFACE ${CMAKE_SOURCE_DIR}/src) - - if (USE_PCH_HEADER) - target_precompile_headers(cataclysm-common PRIVATE ${CMAKE_SOURCE_DIR}/pch/main-pch.hpp) - endif () + setup_library(cataclysm-common) if (WIN32) add_executable(cataclysm ${MAIN_CPP} ${MESSAGES_CPP} ${RESOURCE_RC}) @@ -133,47 +90,15 @@ if (CURSES) add_executable(cataclysm ${MAIN_CPP} ${MESSAGES_CPP}) endif () - if (LUA) - target_compile_definitions(cataclysm-common PUBLIC LUA) - target_include_directories(cataclysm-common PUBLIC ${CMAKE_SOURCE_DIR}/src) - target_include_directories(cataclysm-common PUBLIC ${CMAKE_SOURCE_DIR}/src/lua) - endif () - - add_dependencies(cataclysm-common get_version) target_link_libraries(cataclysm cataclysm-common) target_include_directories(cataclysm-common PUBLIC ${CURSES_INCLUDE_DIR}) target_link_libraries(cataclysm-common ${CURSES_LIBRARIES}) - if (CMAKE_USE_PTHREADS_INIT) - target_compile_options(cataclysm-common PUBLIC "-pthread") - endif () - - if (CMAKE_THREAD_LIBS_INIT) - target_link_libraries(cataclysm-common ${CMAKE_THREAD_LIBS_INIT}) - endif () - - if (WIN32) - # Global settings for Windows targets (at end) - 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(cataclysm-common dbghelp.lib) - endif () - endif () - - if (LIBBACKTRACE) - target_link_libraries(cataclysm-common backtrace) - endif () - if (RELEASE) install(TARGETS cataclysm DESTINATION ${BIN_PREFIX}) endif () + endif () if (MINGW AND NOT RELEASE) diff --git a/src/SetupLibrary.cmake b/src/SetupLibrary.cmake new file mode 100644 index 000000000000..1aa47165f4d4 --- /dev/null +++ b/src/SetupLibrary.cmake @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-3.0-only +# Author: 2023 scarf + +function (setup_library TARGET) + + add_library(${TARGET} OBJECT ${CATACLYSM_BN_SOURCES} ${CATACLYSM_BN_HEADERS} ${LUA_C_SOURCES}) + target_include_directories(${TARGET} INTERFACE ${CMAKE_SOURCE_DIR}/src) + + add_dependencies(${TARGET} get_version) + + if (USE_PCH_HEADER) + target_precompile_headers(${TARGET} PRIVATE ${CMAKE_SOURCE_DIR}/pch/main-pch.hpp) + endif () + + if (CMAKE_USE_PTHREADS_INIT) + target_compile_options(${TARGET} PUBLIC "-pthread") + endif () + + if (CMAKE_THREAD_LIBS_INIT) + target_link_libraries(${TARGET} ${CMAKE_THREAD_LIBS_INIT}) + endif () + + if (LUA) + target_compile_definitions(${TARGET} PUBLIC LUA) + target_include_directories(${TARGET} PUBLIC ${CMAKE_SOURCE_DIR}/src) + target_include_directories(${TARGET} PUBLIC ${CMAKE_SOURCE_DIR}/src/lua) + endif () + + if (WIN32) + # Global settings for Windows targets (at end) + target_link_libraries(${TARGET} gdi32.lib) + target_link_libraries(${TARGET} winmm.lib) + target_link_libraries(${TARGET} imm32.lib) + target_link_libraries(${TARGET} ole32.lib) + target_link_libraries(${TARGET} oleaut32.lib) + target_link_libraries(${TARGET} version.lib) + + if (BACKTRACE) + target_link_libraries(${TARGET} dbghelp.lib) + endif () + endif () + + if (LIBBACKTRACE) + target_link_libraries(${TARGET} backtrace) + endif () + +endfunction () diff --git a/tools/clang-tidy-plugin/CMakeLists.txt b/tools/clang-tidy-plugin/CMakeLists.txt index baf4cbe53f50..4bd854d2ab1a 100644 --- a/tools/clang-tidy-plugin/CMakeLists.txt +++ b/tools/clang-tidy-plugin/CMakeLists.txt @@ -30,6 +30,11 @@ target_include_directories(CataAnalyzerPlugin SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS ${CLANG_INCLUDE_DIRS}) if ("${CATA_CLANG_TIDY_INCLUDE_DIR}" STREQUAL "") + # suppress DOWNLOAD_EXTRACT_TIMESTAMP warning + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") + cmake_policy(SET CMP0135 NEW) + endif () + set(CTPS_RELEASES https://github.com/jbytheway/clang-tidy-plugin-support/releases/download) set(CTPS_VERSION llvm-12.0.0-r3) set(CTPS_SRC ${CMAKE_CURRENT_BINARY_DIR}/clang-tidy-plugin-support) From 879c61970bf514b86ab51d4a6e3dafd1076fe92c Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 01:35:29 +0900 Subject: [PATCH 15/28] ci: use merge queue (#3252) --- .github/workflows/matrix.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 110d9b436669..448b70bbe069 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -7,6 +7,9 @@ on: paths-ignore: - doc/** - 'scripts/**' + merge_group: + branches: + - upload pull_request: branches: - upload From ba964778e1915d96c017c7ffccefca29157ecfad Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 19:19:08 +0900 Subject: [PATCH 16/28] docs: `lang/notes` (#3207) * docs: move `lang/notes` into `doc/` * docs(i18n): rename to more fitting name * docs(i18n): localize language-specific translation notes * docs: rewrite edge_cases.md added proper links to relevent pages * feat: lab JSON guide to docs --- data/json/mapgen/lab/README.md | 126 +----------- doc/astro.config.ts | 4 +- .../content/docs/de/i18n/explanation/style.md | 127 ++++++++++++ .../docs/en/i18n/explanation/file_format.md | 188 ++++++++++++++++++ .../content/docs/en/i18n/explanation/style.md | 46 +++++ .../{manual_of_style.md => style_all.md} | 4 +- .../docs/en/i18n/reference/edge_cases.md | 29 ++- .../docs/en/mod/json/guides/map/lab.md | 163 +++++++++++++++ .../en/mod/json/guides/{ => map}/mapgen.md | 42 ++-- .../content/docs/ru/i18n/explanation/style.md | 87 ++++++++ lang/notes/README_all_translators.md | 142 ------------- lang/notes/de.txt | 122 ------------ lang/notes/ru.txt | 69 ------- 13 files changed, 657 insertions(+), 492 deletions(-) mode change 100644 => 120000 data/json/mapgen/lab/README.md create mode 100644 doc/src/content/docs/de/i18n/explanation/style.md create mode 100644 doc/src/content/docs/en/i18n/explanation/file_format.md create mode 100644 doc/src/content/docs/en/i18n/explanation/style.md rename doc/src/content/docs/en/i18n/explanation/{manual_of_style.md => style_all.md} (90%) create mode 100644 doc/src/content/docs/en/mod/json/guides/map/lab.md rename doc/src/content/docs/en/mod/json/guides/{ => map}/mapgen.md (97%) create mode 100644 doc/src/content/docs/ru/i18n/explanation/style.md delete mode 100644 lang/notes/README_all_translators.md delete mode 100644 lang/notes/de.txt delete mode 100644 lang/notes/ru.txt diff --git a/data/json/mapgen/lab/README.md b/data/json/mapgen/lab/README.md deleted file mode 100644 index 8df692ee5804..000000000000 --- a/data/json/mapgen/lab/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# Lab JSON Quick Guide - -Labs are heavily randomized but have very few actual overmap terrain tiles, meaning that variety in the maps gets almost entirely using JSON. In particular, labs use place_nested extensively to randomly select submaps, such as new lab rooms. - - -## Quick Guide for new lab areas: - -In lab_floorplans.json add a new mapgen json with om_terrain of lab_4side. - -Keep the middle 2 spaces of each border clear, because that's where doors open out to. Some or all of the border spaces will be turned into 1-width walls between lab sections, so make sure the map 'works' whether or not the outermost spaces are created or not (by keeping them clear, or having 'disposable' furniture like counters, lockers, broken consoles, etc). Allow rotation. - -To add a lab finale instead, use the om_terrain of lab_finale_1level and put your JSON in lab_floorplans_finale1level.json instead. - - -## Quick Guide for new lab dead-ends: - -In lab_floorplans_1side.json add a new mapgen json with om_terrain of lab_1side. - -Make the area facing north, keeping the 2 middle spaces of the northern border clear because that's where doors open out to. If you want to have a locked area, set the floor to 't_strconc_floor' and stairs won't appear there (this floor is ',' in the lab_palette). Use place_nested to place 'lab_1side_border_doors' at coords [0,0]. Do not allow rotation. - - -## Quick Guide for new lab rooms: - -In lab_rooms.json add a new mapgen json with a nested_mapgen_id of lab_room_7x7 or lab_room_9x9 with a mapgensize of [7,7] or [9,9]. - -In some rare cases the first row or column of terrain may be replaced with a border wall, so prefer layouts that look intact even if that occurs. - -If your layout needs to know where the doors of the room will open up into, instead use a nested_mapgen_id of lab_room_7x7_crossdoors and lab_room_9x9_crossdoors which will ensure that doors only appear in the exact middle of a wall. - - -# Lab JSON Full Guide - -## How area mapgen json works - -A lab is mostly made out of overmap tiles of type 'lab', 'lab_stairs', and typically one 'lab_finale'. - -Lab terrain needs special treatment: stairs, border walls, dead-ends, and more, so JSON instead uses three 'fake' overmap tile types. Create a JSON mapgen object with om_terrain set to one of these, and the code will convert it and place it correctly on the map. - -* lab_1side - placed when exactly one lab is adjacent, maps should assume a north-facing entrance. Do not allow rotation. -* lab_finale_1level - placed at the bottom of a lab on terrain types. Rotation optional. -* lab_4side - all the other maps. Rotation optional. - - -## Border walls - -Labs have unusual borders: 1-width walls between lab areas, laid out on the south and east side of those tiles, potentially with metal doors in the middle of them, like so: - -``` - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " M", - " M", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - " |", - "-----------MM----------|" -``` - -If a north or west neighbor isn't a lab, the entire side gets needs to be overwritten with a wall, replacing whatever was normally there. If the east or south neighbor isn't a lab, that door needs to be overwritten with a wall. - -Some JSON maps can start from the above layout, disable rotation, and call place_nested with the 'lab_border_walls' chunk in JSON. In this case, borders will be perfect and no additional code will fire. - -But if borders have not been managed (determined by checking for the presence of an east-facing door/wall), then the code will create the lab border walls and doors on all four directions. - -'lab_border_walls' does not work on rotated maps, so rotated maps need to rely on hardcoded border wall generation. This is preferable because it creates more variety. So if a map layout is amenable to not knowing if the final 1x1 border around it will be placed or not, it is preferable to allow rotation and not place 'lab_border_walls'. - -One middle-ground: If just part of the map needs to cares about where the border wall is to look correct, put a wall on the east-side of the map and only allow rotation of [0,1]. That will ensure the wall gets placed on the east or south side of the map in the final rotation. See the "electricity room" floorplan for an example of this. - - -## Other hardcoded map generation - -Labs will have a small chance of randomly getting lights, the central & tower labs will always get them. Stairs will be placed on any empty thconc_floor space if the overmap indicated stairs. There's also a 10% chance of special effects like flooding, portals, radiation accidents, etc. Ant-infested labs will get bashed in. - -None of these require json changes to enact, but JSON-ideas for lab special effects in rooms can be added to the spawn tables in lab_maybe_effects_7x7 and lab_maybe_effects_9x9. Currently this just adds spider-infestations. - - -## Room generation - -The most common source of randomness *within* a map is to create a 7x7 or 9x9 room and give it random contents by using place_nested. Don't place rooms directly, instead we use an intermediate map chunk called a 'spawn' which encodes more information and randomizes between all the kinds of rooms that would satisify those requirements. - -* lab_spawn_7x7 - a 7x7 room with no guarantees on where the doors are. -* lab_spawn_7x7_crossdoors - a 7x7 room with doors only in the middle of each border wall. -* lab_spawn_9x9 - a 9x9 room with no guarantees on where the doors are. -* lab_spawn_9x9_crossdoors - a 9x9 room with doors only in the middle of each borders wall. - -Selecting a spawn will randomize between: lab_room_[size] plus the _rare variants, and the _crossdoors variants if applicable. - -If your room is also amenable to having two of its walls redefined, you can also use these spawns to add in more randomized rooms that might modify the walls by adding windows, replacing walls with chainlink, or creating multiple doors and interior walls. These templates assume that there are no doors on the two walls which are not part of this submap. Note these submaps are sized 8x8 and 10x10 because they include the walls to be modified. - -* lab_spawn_7x7_wall_nw -* lab_spawn_7x7_wall_sw -* lab_spawn_9x9_wall_nw -* lab_spawn_9x9_wall_sw - -Use the most specific spawn possible. - - -## Directory - -* lab_central.json - hardcoded maps for the top of central lab. -* lab_common.json - terrain palette, loot palettes, common json objects. -* lab_escape.json - maps specifically for lab challenge escape, these are special placed on lvl 4 of a lab. -* lab_floorplan_cross.json - cross floorplans are unusual for having rock infill when bordering the edge of the lab, with rare vaults. -* lab_floorplans.json - the main source of lab layouts. -* lab_floorplans_1side.json - dead-end floor plans. -* lab_floorplans_finale1level.json - finale floorplans. -* lab_rooms.json - randomized rooms. -* lab_rooms_wall.json - randomized rooms which rewrite the wall borders. -* lab_trains.json - tiles for the lab science train which rarely happens on levels 2 & 4. \ No newline at end of file diff --git a/data/json/mapgen/lab/README.md b/data/json/mapgen/lab/README.md new file mode 120000 index 000000000000..9fd0f753b651 --- /dev/null +++ b/data/json/mapgen/lab/README.md @@ -0,0 +1 @@ +doc/src/content/docs/en/mod/json/guides/map/lab.md \ No newline at end of file diff --git a/doc/astro.config.ts b/doc/astro.config.ts index 714747ad255a..3400f666f775 100644 --- a/doc/astro.config.ts +++ b/doc/astro.config.ts @@ -1,8 +1,8 @@ import { join } from "node:path" import { fileURLToPath } from "node:url" -import { defineConfig } from "astro/config" import starlight from "@astrojs/starlight" +import { defineConfig } from "astro/config" import starlightLinksValidator from "starlight-links-validator" import { loadEnv } from "vite" @@ -40,7 +40,9 @@ export default defineConfig({ defaultLocale: "en", locales: { en: { label: "English" }, + de: { label: "Deutsch", lang: "de-DE" }, ko: { label: "한국어", lang: "ko-KR" }, + ru: { label: "Русский", lang: "ru-RU" }, }, logo: { src: "./src/assets/icon-round.svg" }, social: { github, discord }, diff --git a/doc/src/content/docs/de/i18n/explanation/style.md b/doc/src/content/docs/de/i18n/explanation/style.md new file mode 100644 index 000000000000..7349ee2084de --- /dev/null +++ b/doc/src/content/docs/de/i18n/explanation/style.md @@ -0,0 +1,127 @@ +--- +title: German Style Guide +--- + +Diese Datei enthält Anmerkungen für alle, die das Spiel ins Deutsche übersetzen wollen. + +--- + +## Sprache + +Deutsch wie in Deutschland üblich (de_DE). Wir verwenden die neue deutsche Rechtschreibung. + +## Zusammenfassung + +- Anführungszeichen: »Beispieltext« +- Innere Anführungszeichen: ›Beispieltext‹ +- Anrede: Grundsätzlich mit »du«, mit Ausnahmen (s.u.) +- Strings wie »the %s« oder »a %s« werden besonders übersetzt (s.u.) + +## Anrede + +Grundsätzlich duzen sich alle. Auch der Spieler wird geduzt. + +Die Idee ist, dass nach der Apokalypse das »Sie« einfach aus der Mode kommt. Sind ja nicht mehr +viele übrig. ;-) + +Die förmliche Anrede mit »Sie« wird nur in seltenen Ausnahmefällen benutzt. Diese Ausnahmefälle +sind: + +- Alte Dokumente aus der Zeit vor der Apokalypse, wo die förmliche Anrede Sinn ergibt, z.B. alte + Behördenprotokolle +- Computer, Terminals und die meisten anderen Bedienelemente +- Wenn es sinnvoll erscheint, auch bestimmte NPC-Dialoge, aber das dann bitte unbedingt im Spiel + testen! + +Auf keinen Fall darf völlig grundlos zwischen »du« und »Sie« hin- und hergesprungen werden. + +## Blöde Sonderregel für Artikel + +Es kommen sehr viele Strings vor, bei dem ein Artikel gefolgt von einem Platzhalter auftaucht. Das +ist problematisch für uns, da deutsche Substantive ein Geschlecht haben. + +Zusammenfassung ############### + +Steht ein Artikel vor einem Platzhalter, wird er wie folgt übersetzt (naja): + +- »the %s« → »%s« +- »a %s« → »1 %s« + +Beispiele: + +- »You hit the %s!« → »Du triffst %s!« +- »You see a %s.« → »Du siehst 1 %s.« + +Ausnahmen sind natürlich erlaubt. + +Bestimmter Artikel »the« ######################## + +Beispiel: »You hit the %s!«. + +Problematische Übersetzung: + +- »Du triffst das %s!«. + +So einfach ist das leider nicht, denn wir wissen ja nicht, welches Geschlecht das Wort für %s hat. + +Das funktioniert, wenn %s für »Monster« steht (»das Monster«). Aber wenn %s zu »Spinne« wird, dann +kriegen wir »das Spinne«. Das ist blöd. :-( + +Wir haben uns daher angewöhnt, den Artikel einfach ganz wegzulassen. Also als ob %s ein Name wäre. + +Also: + +- »Du triffst %s!« + +Das ist zwar immer noch nicht schön, aber besser als »das Spinne«. + +Alternativ hat sich auch der Doppelpunkt bewährt. Also: + +- »Du triffst: %s« + +Bei kurzen Strings kann das sinnvoll sein, bei langen Strings eher nicht. + +Unbestimmter Artikel »a«/»an« ############################# + +Beispiel: »On the ground you see a %s.« + +Problematische Übersetzung: »Auf dem Boden siehst du ein %s.« + +Wenn wieder die Spinne kommt, haben wir »ein Spinne«. Das ist doof. :-( + +Notlösung: Wir ersetzen einfach den unbestimmten Artikel mit »1«. Also: + +- »Auf dem Boden siehst du 1 %s.« + +Zugegeben, etwas gefudelt ist das schon. Aber es funktioniert! Irgendwie. :D + +Auch hier wäre der Ansatz mit dem Doppelpunkt denkbar, aber nur, wenn es sein muss. + +Anmerkung ######### + +Beachte: All diese Ansätze sind nur Notlösungen! + +Eine echte Lösung des Problems kann es eigentlich nur geben, wenn die Art, wie C:DDA diese Strings +aufbaut, grundsätzlich ändert. :-( + +## Problemwort: »bionics« + +C:DDA verwendet »bionic« als Wort für eine Art Implantat, nicht für ein Konzept wie in Wikipedia +beschrieben (s.u.). + +So übersetzen wir es: + +- »the bionic« → »das Bionik« +- »the bionics« → »die Bioniken« + +»bionic« wird auch manchmal als Adjektiv eingesetzt: + +- »bionic« → »bionics« + +Aus der englischsprachigen Wikipedia: Bionics (also known as biomimicry, biomimetics, +bio-inspiration, biognosis, and close to bionical creativity engineering) is the application of +biological methods and systems found in nature to the study and design of engineering systems and +modern technology + +Aus der deutschsprachigen Wikipedia: Die Bionik (auch Biomimikry, Biomimetik oder Biomimese) +beschäftigt sich mit dem Übertragen von Phänomenen der Natur auf die Technik. diff --git a/doc/src/content/docs/en/i18n/explanation/file_format.md b/doc/src/content/docs/en/i18n/explanation/file_format.md new file mode 100644 index 000000000000..4f337b9696e5 --- /dev/null +++ b/doc/src/content/docs/en/i18n/explanation/file_format.md @@ -0,0 +1,188 @@ +--- +title: Translation file format (.po) +--- + +Translations are stored in [`".po"` files (Portable Object)][po], named with a language code +specific to each language and country. So for example the translations for the Spanish spoken in +Spain would be found in `es_ES.po` and for Spanish spoken in Mexico would be found in `es_MX.po`. + +[po]: https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html + +It is a plain-text filetype, so you can edit it however you choose, but translators often prefer to +use purpose-built translation editors (such as [Poedit](https://poedit.net)), or web-based +translation tools (such as ). + +The format of `".po"` files is a list of entries, with the english phrase to be translated, followed +by the local translation. The english phrase is on the line or lines beginning with `msgid`, and the +translated phrase goes on the line or lines beginning with `msgstr`. + +Before the `msgid` line there will be a comment line indicating where in the source code the word or +phrase came from. This can often help when the meaning of the english is not obvious. There may also +be comments left by the developers to make translation easier. + +Most entries will look something like this: + +``` +#: action.cpp:421 +msgid "Construct Terrain" +msgstr "niarreT tcurtsnoC" +``` + +The english phrase here is "Construct Terrain", and it comes from line 421 of the file "action.cpp". +The example translation is just a reversal of the english letters. With this, in stead of "Construct +Terrain", the game will display "niarreT tcurtsnoC". + +Another exmple is: + +``` +#: action.cpp:425 defense.cpp:635 defense.cpp:701 npcmove.cpp:2049 +msgid "Sleep" +msgstr "pleeS" +``` + +This is similar to the last example, except it is a more common phrase. It is used in the files +action.cpp, defense.cpp (twice) and npcmove.cpp. The translation will replace every usage. + +## File Header + +The header at the top of the `".po"` file is the only part that differs from the +comment/msgid/msgstr format. + +If you are working on an already established translation you will not have to modify it. + +For a new translation, it should be mostly set up for you, either by the editor you are using or by +the `msginit` program which is the recommended way of initializing a translation (see +TRANSLATING.md). + +If you are starting from another translation file however, you might need to change a few things. +Just fill it in as best you are able. + +The header will look something like: + +``` +# French translations for Cataclysm-DDA package. +# Copyright (C) 2013 CleverRaven and Cataclysm-DDA contributors. +# This file is distributed under the same license as the Cataclysm-DDA package. +# Administrator , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.7-git\n" +"Report-Msgid-Bugs-To: http://github.com/CleverRaven/Cataclysm-DDA\n" +"POT-Creation-Date: 2013-08-01 13:44+0800\n" +"PO-Revision-Date: 2013-08-01 14:02+0800\n" +"Last-Translator: YOUR NAME \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +``` + +If you are starting a new translation, or you are in charge of the existing translation, it is +helpful if you include your name and e-mail address so that you can be contacted with any questions +or issues regarding the translation. + +The only important part that cannot be easily filled out manually is the `Plural-Forms` section. It +determines how different numbers of things are handled in your language. More on that later. + +## Format strings and newlines + +Some strings will have special terms such as `%s`, `%2$d` and `\n`. + +`\n` represents a linebreak. Mostly these are unnecessary as the code wraps lines where it can, but +sometimes these are used for placing things on different lines. Just use `\n` in your translation +wherever a new line should go. + +`%s` and other similar terms are replaced with something else when the game is running. You might +need to move them around, depending on the translation. It is important that every term beginning +with `%` is kept in the translation. + +Here is an example which replaces a `%d` with a number: + +``` +#: addiction.cpp:224 +#, c-format +msgid "" +"Strength - %d; Perception - 1; Dexterity - 1;\n" +"Depression and physical pain to some degree. Frequent cravings. Vomiting." +msgstr "" +";1 - ytiretxeD ;1 - noitpecreP ;%d - htgnertS\n" +".gnitimoV .sgnivarc tneuqerF .eerged emos ot niap lacisyhp dna noisserpeD" +``` + +Here it is important that the `%d` was not reversed, and that the `\n` remained at the end of the +line. In this case, `%d` will be replaced with the character's strength modifier when the message is +displayed. + +In some cases it might be necessary to change the order of terms. This can confuse the game. If the +order of the `%` terms changes, you must add numbers to all of them, so that the game knows which +was which. Some strings will already have these numbers, but some might not. + +As an example, if there is a string with `%s shoots %s!`, it might change in translation. Perhaps it +will become something like `%s is shot by %s!`. But now it is the wrong way around, the shooter has +swapped with the shootee. + +In this case, each `%s` should be numbered with a digit (1-9) then a dollar sign ($) between the `%` +and the `s`. For example `%1$s shoots %2$s!` would be equivalent to `%s shoots %s!`. So the example +translation above could be `%2$s is shot by %1$s!`, and this would work correctly. + +The game can figure out these `%1$s` `%2$s` parameters automatically, but you must make sure that +(A): all of the `%` terms in the translation are numbered; and (B): the numbers are correct in terms +of the original ordering in the english text. + +For example: + +``` +#: map.cpp:680 +#, c-format +msgid "%s loses control of the %s." +msgstr "%2$s eht fo lortnoc sesol %1$s" +``` + +would be displayed in-game as `kcurt eht fo lortnoc sesol liagibA`, assuming `Abigail` was driving a +`truck`. + +## Special tags in strings + +Some strings in the translation may have special tags in front of or inside them. These tags should +be left as-is, and only the rest of the string translated. + +For example, the NPC and city names from "data/raw/names.json" are prefixed with `` so as to +avoid conflicts with words (such as `Wood` the material, and `Wood` the last name). For these, the +`` part should be left in. + +For example: + +``` +#. ~ proper name; gender=female; usage=given +#: lang/json/json_names.py:6 +msgid "Abigail" +msgstr "liagibA" +``` + +Names also have a comment above them, indicating what the name is used for in-game. In this case, +`Abigail` is a possible first name for a female NPC. + +## Plural forms + +Many languages use different terms for things depending on how many of them there are. These are +supported using plural forms, defined by the `Plural-Form` line in the `".po"` file header. + +For these, there will be multiple `msgstr` lines, intended for the different forms depending on +number. The game will automatically choose the correct form depending on the number of things. + +For example: + +``` +#: melee.cpp:913 +#, c-format +msgid "%d enemy hit!" +msgid_plural "%d enemies hit!" +msgstr[0] "!tih ymene %d" +msgstr[1] "!tih seimene %d" +``` + +Here the first entry is for when there is only one `enemy`, the second is for when there are more +than one `enemies`. The rules differ wildly between languages. diff --git a/doc/src/content/docs/en/i18n/explanation/style.md b/doc/src/content/docs/en/i18n/explanation/style.md new file mode 100644 index 000000000000..82366da9e211 --- /dev/null +++ b/doc/src/content/docs/en/i18n/explanation/style.md @@ -0,0 +1,46 @@ +--- +title: Language Specific Style Guide +--- + +:::note{title="This section is a template."} + +As this page is for language-specific notes, it shouldn't be translated. Instead, it's used as a +template. [Check here for examples.](#writing-style-guide-for-your-language) + +::: + +## How to write one for your language + +1. [Find your language code.](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) +2. Create `doc/src/content/docs/{your-language-code}/i18n/explanation/style.md`. +3. If it doesn't, add your language to `doc/astro.config.ts` file, for example: + +```diff +diff --git a/doc/astro.config.ts b/doc/astro.config.ts +index da91c2e0014..3dafa248a06 100644 +--- a/doc/astro.config.ts ++++ b/doc/astro.config.ts +@@ -41,6 +41,7 @@ export default defineConfig({ + locales: { + en: { label: "English" }, + ko: { label: "한국어", lang: "ko-KR" }, ++ ru: { label: "Русский", lang: "ru-RU" }, + }, + logo: { src: "./src/assets/icon-round.svg" }, + social: { github, discord }, +``` + +In this example, it will allow russian language to be availble in language selector. Check +[starlight](https://starlight.astro.build/guides/i18n/) for details. + +## Writing style guide for your language + +There's no restrictions on how or what to write in this file. For example, you could: + +- write language specific notes for other translaotrs to read +- link to external resources or tools + +You could check out existing style guides for reference: + +- [Deutsch](../../../de/i18n/explanation/style.md) +- [Russian](../../../ru/i18n/explanation/style.md) diff --git a/doc/src/content/docs/en/i18n/explanation/manual_of_style.md b/doc/src/content/docs/en/i18n/explanation/style_all.md similarity index 90% rename from doc/src/content/docs/en/i18n/explanation/manual_of_style.md rename to doc/src/content/docs/en/i18n/explanation/style_all.md index 8df7b5848670..02624878f10f 100644 --- a/doc/src/content/docs/en/i18n/explanation/manual_of_style.md +++ b/doc/src/content/docs/en/i18n/explanation/style_all.md @@ -1,8 +1,8 @@ --- -title: translation style guide +title: General Style Guide --- -Follow these conventions when adding or editing in-game text: +Please follow these conventions when adding or editing in-game text: 1. Use US English spelling. 2. Use double sentence spacing after periods. This means that a period that ends a sentence should diff --git a/doc/src/content/docs/en/i18n/reference/edge_cases.md b/doc/src/content/docs/en/i18n/reference/edge_cases.md index fe6338e8627b..73cb8ba76b07 100644 --- a/doc/src/content/docs/en/i18n/reference/edge_cases.md +++ b/doc/src/content/docs/en/i18n/reference/edge_cases.md @@ -2,17 +2,26 @@ title: Edge cases --- -There are issues specific to Cataclysm: BN which translators should be aware of. These include the -use of terms like `%s` and `%3$d` (leave them as they are), and the use of tags like ``, which -shouldn't be translated. +There are issues specific to Cataclysm: BN which translators should be aware of. For example: -Information about these and any other issues specific to individual languages, can be found in -Cataclysm: BN's [language notes folder][notes]. +## Special Symbols -[notes]: https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/lang/notes +Some translation texts will have special symbols or formatting, such as -General notes for all translators are in `README_all_translators.txt`, and notes specific to a -language may be stored as `.txt`, for example `de.txt` for German. +- [`%s` and `%3$d` (should be leave them as they are)](../explanation/file_format.md#format-strings-and-newlines) +- [`` (shouldn't be translated)](../explanation/file_format.md#special-tags-in-strings) -Cataclysm: BN has more than 14000 translatable strings, but don't be discouraged. The more -translators there are, the easier it becomes 😄. +To learn more, please read the [file format explanation](../explanation/file_format.md). + +## Language Specific Guidelines + +Check the following files for specific guidelines: + +- [General notes for all translators (mostly english)](../explanation/style_all.md) +- [Notes specific to a language](../explanation/style.md) + +Cataclysm: BN has more than 46,000 translatable strings (last updated at 2023-09-22 [^1]), but don't +be discouraged. The more translators there are, the easier it becomes! + +[^1]: Transifex API does not expose a public endpoint (at least without bearer token), so we were +unable to update the number automatically.) diff --git a/doc/src/content/docs/en/mod/json/guides/map/lab.md b/doc/src/content/docs/en/mod/json/guides/map/lab.md new file mode 100644 index 000000000000..4272480de71f --- /dev/null +++ b/doc/src/content/docs/en/mod/json/guides/map/lab.md @@ -0,0 +1,163 @@ +--- +title: Writing Lab JSON +--- + +Labs are heavily randomized but have very few actual overmap terrain tiles, meaning that variety in +the maps gets almost entirely using JSON. In particular, labs use place_nested extensively to +randomly select submaps, such as new lab rooms. + +## Quick Guide for new lab areas: + +In lab_floorplans.json add a new mapgen json with om_terrain of lab_4side. + +Keep the middle 2 spaces of each border clear, because that's where doors open out to. Some or all +of the border spaces will be turned into 1-width walls between lab sections, so make sure the map +'works' whether or not the outermost spaces are created or not (by keeping them clear, or having +'disposable' furniture like counters, lockers, broken consoles, etc). Allow rotation. + +To add a lab finale instead, use the om_terrain of lab_finale_1level and put your JSON in +lab_floorplans_finale1level.json instead. + +## Quick Guide for new lab dead-ends: + +In lab_floorplans_1side.json add a new mapgen json with om_terrain of lab_1side. + +Make the area facing north, keeping the 2 middle spaces of the northern border clear because that's +where doors open out to. If you want to have a locked area, set the floor to 't_strconc_floor' and +stairs won't appear there (this floor is ',' in the lab_palette). Use place_nested to place +'lab_1side_border_doors' at coords `[0, 0]`. Do not allow rotation. + +## Quick Guide for new lab rooms: + +In lab_rooms.json add a new mapgen json with a nested_mapgen_id of lab_room_7x7 or lab_room_9x9 with +a mapgensize of `[7, 7]` or `[9, 9]`. + +In some rare cases the first row or column of terrain may be replaced with a border wall, so prefer +layouts that look intact even if that occurs. + +If your layout needs to know where the doors of the room will open up into, instead use a +nested_mapgen_id of lab_room_7x7_crossdoors and lab_room_9x9_crossdoors which will ensure that doors +only appear in the exact middle of a wall. + +# Lab JSON Full Guide + +## How area mapgen json works + +A lab is mostly made out of overmap tiles of type 'lab', 'lab_stairs', and typically one +'lab_finale'. + +Lab terrain needs special treatment: stairs, border walls, dead-ends, and more, so JSON instead uses +three 'fake' overmap tile types. Create a JSON mapgen object with om_terrain set to one of these, +and the code will convert it and place it correctly on the map. + +- lab_1side - placed when exactly one lab is adjacent, maps should assume a north-facing entrance. + Do not allow rotation. +- lab_finale_1level - placed at the bottom of a lab on terrain types. Rotation optional. +- lab_4side - all the other maps. Rotation optional. + +## Border walls + +Labs have unusual borders: 1-width walls between lab areas, laid out on the south and east side of +those tiles, potentially with metal doors in the middle of them, like so: + +``` +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" M", +" M", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +" |", +"-----------MM----------|" +``` + +If a north or west neighbor isn't a lab, the entire side gets needs to be overwritten with a wall, +replacing whatever was normally there. If the east or south neighbor isn't a lab, that door needs to +be overwritten with a wall. + +Some JSON maps can start from the above layout, disable rotation, and call place_nested with the +'lab_border_walls' chunk in JSON. In this case, borders will be perfect and no additional code will +fire. + +But if borders have not been managed (determined by checking for the presence of an east-facing +door/wall), then the code will create the lab border walls and doors on all four directions. + +'lab_border_walls' does not work on rotated maps, so rotated maps need to rely on hardcoded border +wall generation. This is preferable because it creates more variety. So if a map layout is amenable +to not knowing if the final 1x1 border around it will be placed or not, it is preferable to allow +rotation and not place 'lab_border_walls'. + +One middle-ground: If just part of the map needs to cares about where the border wall is to look +correct, put a wall on the east-side of the map and only allow rotation of `[0, 1]`. That will +ensure the wall gets placed on the east or south side of the map in the final rotation. See the +"electricity room" floorplan for an example of this. + +## Other hardcoded map generation + +Labs will have a small chance of randomly getting lights, the central & tower labs will always get +them. Stairs will be placed on any empty thconc_floor space if the overmap indicated stairs. There's +also a 10% chance of special effects like flooding, portals, radiation accidents, etc. Ant-infested +labs will get bashed in. + +None of these require json changes to enact, but JSON-ideas for lab special effects in rooms can be +added to the spawn tables in lab_maybe_effects_7x7 and lab_maybe_effects_9x9. Currently this just +adds spider-infestations. + +## Room generation + +The most common source of randomness _within_ a map is to create a 7x7 or 9x9 room and give it +random contents by using place_nested. Don't place rooms directly, instead we use an intermediate +map chunk called a 'spawn' which encodes more information and randomizes between all the kinds of +rooms that would satisify those requirements. + +- lab_spawn_7x7 - a 7x7 room with no guarantees on where the doors are. +- lab_spawn_7x7_crossdoors - a 7x7 room with doors only in the middle of each border wall. +- lab_spawn_9x9 - a 9x9 room with no guarantees on where the doors are. +- lab_spawn_9x9_crossdoors - a 9x9 room with doors only in the middle of each borders wall. + +Selecting a spawn will randomize between: `lab_room_[size]` plus the _rare variants, and the +_crossdoors variants if applicable. + +If your room is also amenable to having two of its walls redefined, you can also use these spawns to +add in more randomized rooms that might modify the walls by adding windows, replacing walls with +chainlink, or creating multiple doors and interior walls. These templates assume that there are no +doors on the two walls which are not part of this submap. Note these submaps are sized 8x8 and 10x10 +because they include the walls to be modified. + +- lab_spawn_7x7_wall_nw +- lab_spawn_7x7_wall_sw +- lab_spawn_9x9_wall_nw +- lab_spawn_9x9_wall_sw + +Use the most specific spawn possible. + +## Directory + +- lab_central.json - hardcoded maps for the top of central lab. +- lab_common.json - terrain palette, loot palettes, common json objects. +- lab_escape.json - maps specifically for lab challenge escape, these are special placed on lvl 4 of + a lab. +- lab_floorplan_cross.json - cross floorplans are unusual for having rock infill when bordering the + edge of the lab, with rare vaults. +- lab_floorplans.json - the main source of lab layouts. +- lab_floorplans_1side.json - dead-end floor plans. +- lab_floorplans_finale1level.json - finale floorplans. +- lab_rooms.json - randomized rooms. +- lab_rooms_wall.json - randomized rooms which rewrite the wall borders. +- lab_trains.json - tiles for the lab science train which rarely happens on levels 2 & 4. diff --git a/doc/src/content/docs/en/mod/json/guides/mapgen.md b/doc/src/content/docs/en/mod/json/guides/map/mapgen.md similarity index 97% rename from doc/src/content/docs/en/mod/json/guides/mapgen.md rename to doc/src/content/docs/en/mod/json/guides/map/mapgen.md index 446bb9354dbf..f61d4d8d84c6 100644 --- a/doc/src/content/docs/en/mod/json/guides/mapgen.md +++ b/doc/src/content/docs/en/mod/json/guides/map/mapgen.md @@ -5,18 +5,18 @@ title: Guide for basic mapgen This guide will cover the basics of mapgen, which files you need to edit, the tags in each file and the differences in creating specials or regular city buildings. -[For full technical information about mapgen entries, visit here](../reference/map/mapgen) +[For full technical information about mapgen entries, visit here](../../reference/map/mapgen) First, lets cover some basic concepts and the files you'll add or edit. -#### General comments: +## General comments: CDDA mapgen is surprisingly powerful once you get used to working with it. You can use lots of tricks to add variability and interest to your maps. Most advanced mapgen techniques will go into a different tutorial. This one covers basic concepts and how to create a basic single OMT (overmap terrain tile)sized building. We will touch on palette usage and how to add a roof as well. -#### Specials vs. city buildings: +## Specials vs. city buildings: A special is a building that spawns outside the city and requires additional information to spawn, like its distance from cities and valid OMT terrain types. They also used to be the only multi-tile @@ -31,7 +31,7 @@ Important policy: since the roof project, all buildings are now multi-tile acros buildings should always get a JSON roof added. Soon, all basements will also be custom fit to the ground floor mapgen, so it is good practice to include dedicated downstairs if you want a basement. -#### The Files & their purpose: +## The Files & their purpose: 1. You will add a new mapgen file in: [data/json/mapgen](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/data/json/mapgen) @@ -64,7 +64,7 @@ ground floor mapgen, so it is good practice to include dedicated downstairs if y - Please avoid editing existing mapgen palettes because you may affect existing maps using a combination of the palette and the mapgen file. -#### Starting the mapgen entry: +## Starting the mapgen entry: When I start a new map project, I generally will add in all the entries I need for it to spawn in game from the outset. This way I can test it as I work on it and adjust it as needed. So, I @@ -83,15 +83,15 @@ Before beginning you’ll want to make some decisions: - Will I be using the mapgen object data in combination with a palette (see the mall 2nd floor if you want a master class in combined usage of both types)? -#### The mapgen map: +## The mapgen map: This covers the mapgen file map flags and what they do in layman’s terms. You can get more extensive -information from [MAPGEN](../reference/map/mapgen). +information from [MAPGEN](../../reference/map/mapgen). the mapgen file has some meta data tags and the `"object"` data which defines everything to make the map. -##### The metadata: +### The metadata: Sample: @@ -116,7 +116,7 @@ Sample: determine how often each spawns in relation to the other. Say the furnished house is at 100, and the abandoned one is at 20. So, it'll spawn 5x less than the furnished house. -##### The object data: +### The object data: This is the section of tags that defines your map, its terrains, furniture, and various spawn types. There are several ways to place items (and nested maps). These deserve their own tutorial. For this @@ -289,7 +289,7 @@ can put any item_group into the machines, like those bullet ones_. 6. Item spawns: There are many ways to place items. This tutorial will only cover explicit symbol placement which is the easiest. There is documentation all about loot spawns you can read for - further information. See: [ITEM_SPAWN.md](../reference/items/ITEM_SPAWN). + further information. See: [ITEM_SPAWN.md](../../reference/items/ITEM_SPAWN). our sample uses "items": for its tag. others include: "place_item", "place_items", "place_loot". Some of these allow for individual item placement and others groups, or both. This will be covered @@ -434,7 +434,7 @@ finally for flowers (which are furniture): "p": "f_region_flower" ``` -#### Adding the roof! +## Adding the roof! Almost all CDDA buildings are now roof-capable and we'd love to keep it that way. Make sure to submit a roof map with your building. This can go into the same file as your ground floor and any @@ -494,9 +494,9 @@ sample roof: "t_shingle_flat_roof" in this mapgen which will override the palettes entry for `".": "t_flat_roof"`. (more on this in advanced mapgen). -I have a separate roof document at: [JSON_ROOF_MAPGEN](./JSON_ROOF_MAPGEN). +I have a separate roof document at: [JSON_ROOF_MAPGEN](../JSON_ROOF_MAPGEN). -#### Linking various mapgen maps using multitile_city_buildings.json +## Linking various mapgen maps using multitile_city_buildings.json This file is found at: [data/json/overmap/multitile_city_buildings.json](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/data/json/overmap/multitile_city_buildings.json). @@ -535,7 +535,7 @@ A standard entry: is the generic basement mapgen group and thus doesn't get `_north` (this will change as we add dedicated stairs to our houses). -#### Setting overmap spawns using regional_map_settings.json +## Setting overmap spawns using regional_map_settings.json [data/json/regional_map_settings.json](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/data/json/regional_map_settings.json) @@ -545,7 +545,7 @@ A standard entry: complain which is why the are often the same name. 4. Choose a good weight for your building. -#### Linking and spawning specials: +## Linking and spawning specials: Put the entry in: [data/json/overmap/overmap_special/specials.json](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/data/json/overmap/overmap_special/specials.json). @@ -596,11 +596,11 @@ Example: percentage so `[ 1, 10 ]` wouldn't be 1 to 10 times per overmap but a 1 in 10% chance to spawn on the overmap. So 10% chance to spawn once per overmap. 8. `"flags"`: These are flags you can use to further define the special. For a list of flags see: - [JSON_FLAGS](../reference/JSON_FLAGS). + [JSON_FLAGS](../../reference/JSON_FLAGS). -Read: [OVERMAP](../reference/map/OVERMAP) for more details. +Read: [OVERMAP](../../reference/map/OVERMAP) for more details. -#### Overmap_terrain entries: +## Overmap_terrain entries: Choose a file for your building type at: [data/json/overmap/overmap_terrain](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/data/json/overmap/overmap_terrain). @@ -644,9 +644,9 @@ You need one entry per mapgen ID: appropriate for your location. Others further define the mapgen, like having sidewalks generate. For further information see: -[Overmap Terrain section of OVERMAP](../reference/map/OVERMAP#overmap-terrain). +[Overmap Terrain section of OVERMAP](../../reference/map/OVERMAP#overmap-terrain). -#### Palettes: +## Palettes: As mentioned earlier, palettes can hold almost all the information that the object entry contains, except for `rows` and `fill_ter`. Their main purpose is to reduce the need to add the same basic @@ -738,7 +738,7 @@ are designed to work together for houses using nested mapgen. There is a palette foundation, another for the nests, and finally another one I've designed for domestic outdoor nested chunks. -#### Final comments: +## Final comments: The information here should be enough for you got get around mapgen and start making maps but there are a lot of variations that will be covered in focused. diff --git a/doc/src/content/docs/ru/i18n/explanation/style.md b/doc/src/content/docs/ru/i18n/explanation/style.md new file mode 100644 index 000000000000..1daac27f4a59 --- /dev/null +++ b/doc/src/content/docs/ru/i18n/explanation/style.md @@ -0,0 +1,87 @@ +--- +title: Russian Style Guide +--- + +This file contains notes/discussion regarding translation for Russian, written in Russian. + +--- + +## Специфика: + +Старайтесь избавляться от англицизмов. Например, "Вы вытащили руки из своих карманов" следует +заменить на "Вы вытащили руки из карманов". + +После перевода перечитайте свой текст. Если по-русски он звучит странно, это повод его несколько +подредактировать с сохранением изначального смысла. + +Замена слов на уменьшительно-ласкательные приветствуется, если они подходят по смыслу. Замена слов +на русский сленг или придание словам большей экспрессии тоже приветствуется, если это соответствует +контексту. Импровизация в рамках контекста и смысла допустима, если конечный текст выглядит лучше, +чем дословный перевод. + +После многоточия, по правилам русского языка, следующее предложение начинается с большой буквы. + +Прямую речь следует писать по русским правилам, если она встречается в переводе. + +Иногда перед началом или в конце фразы стоят пробелы. Их очень плохо видно в редакторе Transifex, +имейте это в виду. Особенно часто это бывает, если фраза не окончена или по смыслу имеет +продолжение. Чтобы лучше видеть такие пробелы, можно зайти в настройки редактора и включить пункт +"Показать пробелы". + +Также не стоит забывать про букву Ё. + +## Формы множественного числа + +В редакторе Transifex некоторые названия предметов требуется переводить для всех форм единственного +и множественного числа. В игре, в зависимости от того, сколько у вас предметов, будет отображаться +название предмета в нужной форме. + +1 — единственное число (например: яблоко) Несколько — нужно подобрать окончание так, чтобы оно +соответствовало кол-ву 2-4 предмета (например: яблока) Много — нужно подобрать окончание так, чтобы +оно соответствовало кол-ву 5-бесконечность предметов (например: яблок) Другое — простая форма +множественного числа (например: яблоки) + +В разделе "Несколько", при переводе прилагательных женского рода следует отдавать предпочтение +варианту: две "стиральные машины", а не две "стиральных машины". + +Что касается книг и журналов. Слово копия и выпуск можно опустить. Как правило, если книги/журналы +имеют множественное число, стоит переводить так: 1: книга «Война миров» Несколько (например, две): +книги «Война миров» Много (например, сто): книг «Война миров» Другое: книги «Война миров» + +1: журнал «Плейбой» Несколько (например, два): журнала «Плейбой» Много (например, сто): журналов +«Плейбой» Другое: журналы «Плейбой» + +Иногда встречаются такие слова, которые не стоит писать в единственном или во множественном числе, +например, "фисташки", "арахис" и т.д. Их надо оставлять в той форме, которая больше подходит по +смыслу. + +## Спецсимволы: + +Спецсимволы печатаются комбинацией клавиш. Для различных операционных систем эти комбинации разные. +Для ОС Windows спецсимволы набираются на цифровой клавиатуре с помощью зажатой клавиши alt. Для ОС +Linux существуют комбинации с кнопкой Compose. Для Mac ОС применяется комбинации с клавишей Option. +Некоторые символы имеют свою специфику в русском языке, отличную от английского. Нужно использовать +русскую интерпретацию, если это возможно. + +Стоит различать тире и дефис. Дефис ставится внутри слова, короткий, без пробелов (например: что-то, +чёрно-белый и т.п.). Тире — пунктуационный знак, ставится между словами, длиннее, отделяется +пробелами с обеих сторон. Дефис: - (минус) Тире: — WIN:(alt + 0151) LIN:(Сompose + - + --) +MAC:(Option + Shift + -) + +Кавычки следует использовать ёлочки. Открывающая кавычка: « WIN:(alt + 0171) LIN:(Сompose + < + <) +MAC:(Option + \) Закрывающая кавычка: » WIN:(alt + 0187) LIN:(Сompose + > + >) MAC:(Option + Shift + +\) + +Иногда, в тексте оригинала встречаются спецсимволы "%s", "%2$d", "\n", а также цветовые теги с +цифрами 1 и 2. Оставляете их как есть, подставляя по смыслу в нужное место. Стоит ставить пробелы +перед и после спецсимволов, если они есть в оригинале. \n — перенос строки (эквивалентно клавише +enter в текстовом редакторе) %2$d или %d — вместо этих символов в игре будет отображаться числовое +значение %2$s или %s — вместо этих символов в игре будет отображаться какая-либо другая строка + +Поскольку шрифт в игре моноширинный, а у некоторых еще и квадратный, стоит соблюдать следующую +специфику. Не стоит использовать три точки вместо многоточия, в игре это очень плохо выглядит. Есть +свой спецсимвол. Многоточие: … WIN:(alt + 0133) LIN:(Сompose + . + .) MAC:(Option + ;) + +Также, в английском языке для текста игры принято правило разделять предложения двумя пробелами. В +русском языке такого правила нет, поэтому после точки в конце предложения должен оставаться один +пробел. diff --git a/lang/notes/README_all_translators.md b/lang/notes/README_all_translators.md deleted file mode 100644 index 9f6676e81eff..000000000000 --- a/lang/notes/README_all_translators.md +++ /dev/null @@ -1,142 +0,0 @@ -# Instructions for Cataclysm-DDA translators - -* [Translation file format](#translation-file-format) -* [Translation file header](#translation-file-header) -* [Format strings and newlines](#format-strings-and-newlines) -* [Special tags in strings](#special-tags-in-strings) -* [Plural forms](#plural-forms) - -## Translation file format - -Translations are stored in ".po" files, named with a language code specific to each language and country. So for example the translations for the Spanish spoken in Spain would be found in "es_ES.po" and for Spanish spoken in Mexico would be found in "es_MX.po". - -It is a plain-text filetype, so you can edit it however you choose, but translators often prefer to use purpose-built translation editors (such as Poedit from poedit.net), or web-based translation tools (such as translations.launchpad.net). - -The format of ".po" files is a list of entries, with the english phrase to be translated, followed by the local translation. The english phrase is on the line or lines beginning with `msgid`, and the translated phrase goes on the line or lines beginning with `msgstr`. - -Before the `msgid` line there will be a comment line indicating where in the source code the word or phrase came from. This can often help when the meaning of the english is not obvious. There may also be comments left by the developers to make translation easier. - -Most entries will look something like this: - - #: action.cpp:421 - msgid "Construct Terrain" - msgstr "niarreT tcurtsnoC" - -The english phrase here is "Construct Terrain", and it comes from line 421 of the file "action.cpp". The example translation is just a reversal of the english letters. With this, in stead of "Construct Terrain", the game will display "niarreT tcurtsnoC". - -Another exmple is: - - #: action.cpp:425 defense.cpp:635 defense.cpp:701 npcmove.cpp:2049 - msgid "Sleep" - msgstr "pleeS" - -This is similar to the last example, except it is a more common phrase. It is used in the files action.cpp, defense.cpp (twice) and npcmove.cpp. The translation will replace every usage. - - -## Translation file header - -The header at the top of the ".po" file is the only part that differs from the comment/msgid/msgstr format. - -If you are working on an already established translation you will not have to modify it. - -For a new translation, it should be mostly set up for you, either by the editor you are using or by the `msginit` program which is the recommended way of initializing a translation (see TRANSLATING.md). - -If you are starting from another translation file however, you might need to change a few things. Just fill it in as best you are able. - -The header will look something like: - - # French translations for Cataclysm-DDA package. - # Copyright (C) 2013 CleverRaven and Cataclysm-DDA contributors. - # This file is distributed under the same license as the Cataclysm-DDA package. - # Administrator , 2013. - # - msgid "" - msgstr "" - "Project-Id-Version: 0.7-git\n" - "Report-Msgid-Bugs-To: http://github.com/CleverRaven/Cataclysm-DDA\n" - "POT-Creation-Date: 2013-08-01 13:44+0800\n" - "PO-Revision-Date: 2013-08-01 14:02+0800\n" - "Last-Translator: YOUR NAME \n" - "Language-Team: French\n" - "Language: fr\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=2; plural=(n > 1);\n" - -If you are starting a new translation, or you are in charge of the existing translation, it is helpful if you include your name and e-mail address so that you can be contacted with any questions or issues regarding the translation. - -The only important part that cannot be easily filled out manually is the `Plural-Forms` section. It determines how different numbers of things are handled in your language. More on that later. - - -## Format strings and newlines - -Some strings will have special terms such as `%s`, `%2$d` and `\n`. - -`\n` represents a linebreak. Mostly these are unnecessary as the code wraps lines where it can, but sometimes these are used for placing things on different lines. Just use `\n` in your translation wherever a new line should go. - -`%s` and other similar terms are replaced with something else when the game is running. You might need to move them around, depending on the translation. It is important that every term beginning with `%` is kept in the translation. - -Here is an example which replaces a `%d` with a number: - - #: addiction.cpp:224 - #, c-format - msgid "" - "Strength - %d; Perception - 1; Dexterity - 1;\n" - "Depression and physical pain to some degree. Frequent cravings. Vomiting." - msgstr "" - ";1 - ytiretxeD ;1 - noitpecreP ;%d - htgnertS\n" - ".gnitimoV .sgnivarc tneuqerF .eerged emos ot niap lacisyhp dna noisserpeD" - -Here it is important that the `%d` was not reversed, and that the `\n` remained at the end of the line. In this case, `%d` will be replaced with the character's strength modifier when the message is displayed. - -In some cases it might be necessary to change the order of terms. This can confuse the game. If the order of the `%` terms changes, you must add numbers to all of them, so that the game knows which was which. Some strings will already have these numbers, but some might not. - -As an example, if there is a string with `%s shoots %s!`, it might change in translation. Perhaps it will become something like `%s is shot by %s!`. But now it is the wrong way around, the shooter has swapped with the shootee. - -In this case, each `%s` should be numbered with a digit (1-9) then a dollar sign ($) between the `%` and the `s`. For example `%1$s shoots %2$s!` would be equivalent to `%s shoots %s!`. So the example translation above could be `%2$s is shot by %1$s!`, and this would work correctly. - -The game can figure out these `%1$s` `%2$s` parameters automatically, but you must make sure that (A): all of the `%` terms in the translation are numbered; and (B): the numbers are correct in terms of the original ordering in the english text. - -For example: - - #: map.cpp:680 - #, c-format - msgid "%s loses control of the %s." - msgstr "%2$s eht fo lortnoc sesol %1$s" - -would be displayed in-game as `kcurt eht fo lortnoc sesol liagibA`, assuming `Abigail` was driving a `truck`. - - -## Special tags in strings - -Some strings in the translation may have special tags in front of or inside them. These tags should be left as-is, and only the rest of the string translated. - -For example, the NPC and city names from "data/raw/names.json" are prefixed with `` so as to avoid conflicts with words (such as `Wood` the material, and `Wood` the last name). For these, the `` part should be left in. - -For example: - - #. ~ proper name; gender=female; usage=given - #: lang/json/json_names.py:6 - msgid "Abigail" - msgstr "liagibA" - -Names also have a comment above them, indicating what the name is used for in-game. In this case, `Abigail` is a possible first name for a female NPC. - - -## Plural forms - -Many languages use different terms for things depending on how many of them there are. These are supported using plural forms, defined by the `Plural-Form` line in the ".po" file header. - -For these, there will be multiple `msgstr` lines, intended for the different forms depending on number. The game will automatically choose the correct form depending on the number of things. - -For example: - - #: melee.cpp:913 - #, c-format - msgid "%d enemy hit!" - msgid_plural "%d enemies hit!" - msgstr[0] "!tih ymene %d" - msgstr[1] "!tih seimene %d" - -Here the first entry is for when there is only one `enemy`, the second is for when there are more than one `enemies`. The rules differ wildly between languages. diff --git a/lang/notes/de.txt b/lang/notes/de.txt deleted file mode 100644 index d06822770eaa..000000000000 --- a/lang/notes/de.txt +++ /dev/null @@ -1,122 +0,0 @@ -This file contains notes/discussion regarding translation for German, written in German. - -------------------- - -Diese Datei enthält Anmerkungen für alle, die das Spiel ins Deutsche übersetzen wollen. - -------------------- - -Sprache -------- -Deutsch wie in Deutschland üblich (de_DE). Wir verwenden die neue deutsche Rechtschreibung. - -Zusammenfassung ------------------ - -* Anführungszeichen: »Beispieltext« -* Innere Anführungszeichen: ›Beispieltext‹ -* Anrede: Grundsätzlich mit »du«, mit Ausnahmen (s.u.) -* Strings wie »the %s« oder »a %s« werden besonders übersetzt (s.u.) - -Anrede ------- -Grundsätzlich duzen sich alle. Auch der Spieler wird geduzt. - -Die Idee ist, dass nach der Apokalypse das »Sie« einfach aus der Mode kommt. Sind ja nicht mehr viele übrig. ;-) - -Die förmliche Anrede mit »Sie« wird nur in seltenen Ausnahmefällen benutzt. Diese Ausnahmefälle sind: - -* Alte Dokumente aus der Zeit vor der Apokalypse, wo die förmliche Anrede Sinn ergibt, z.B. alte Behördenprotokolle -* Computer, Terminals und die meisten anderen Bedienelemente -* Wenn es sinnvoll erscheint, auch bestimmte NPC-Dialoge, aber das dann bitte unbedingt im Spiel testen! - -Auf keinen Fall darf völlig grundlos zwischen »du« und »Sie« hin- und hergesprungen werden. - -Blöde Sonderregel für Artikel ------------------------------ -Es kommen sehr viele Strings vor, bei dem ein Artikel gefolgt von einem Platzhalter auftaucht. Das ist problematisch für uns, da deutsche Substantive ein Geschlecht haben. - -Zusammenfassung -############### - -Steht ein Artikel vor einem Platzhalter, wird er wie folgt übersetzt (naja): - -* »the %s« → »%s« -* »a %s« → »1 %s« - -Beispiele: - -* »You hit the %s!« → »Du triffst %s!« -* »You see a %s.« → »Du siehst 1 %s.« - -Ausnahmen sind natürlich erlaubt. - -Bestimmter Artikel »the« -######################## - -Beispiel: »You hit the %s!«. - -Problematische Übersetzung: -* »Du triffst das %s!«. - -So einfach ist das leider nicht, denn wir wissen ja nicht, welches Geschlecht das Wort für %s hat. - -Das funktioniert, wenn %s für »Monster« steht (»das Monster«). Aber wenn %s zu »Spinne« wird, dann kriegen wir »das Spinne«. Das ist blöd. :-( - -Wir haben uns daher angewöhnt, den Artikel einfach ganz wegzulassen. Also als ob %s ein Name wäre. - -Also: -* »Du triffst %s!« - -Das ist zwar immer noch nicht schön, aber besser als »das Spinne«. - -Alternativ hat sich auch der Doppelpunkt bewährt. Also: -* »Du triffst: %s« - -Bei kurzen Strings kann das sinnvoll sein, bei langen Strings eher nicht. - -Unbestimmter Artikel »a«/»an« -############################# - -Beispiel: »On the ground you see a %s.« - -Problematische Übersetzung: »Auf dem Boden siehst du ein %s.« - -Wenn wieder die Spinne kommt, haben wir »ein Spinne«. Das ist doof. :-( - -Notlösung: Wir ersetzen einfach den unbestimmten Artikel mit »1«. Also: - -* »Auf dem Boden siehst du 1 %s.« - -Zugegeben, etwas gefudelt ist das schon. Aber es funktioniert! Irgendwie. :D - -Auch hier wäre der Ansatz mit dem Doppelpunkt denkbar, aber nur, wenn es sein muss. - -Anmerkung -######### - -Beachte: All diese Ansätze sind nur Notlösungen! - -Eine echte Lösung des Problems kann es eigentlich nur geben, wenn die Art, wie C:DDA diese Strings aufbaut, grundsätzlich ändert. :-( - - - -Problemwort: »bionics« ----------------------- -C:DDA verwendet »bionic« als Wort für eine Art Implantat, nicht für ein Konzept wie in Wikipedia beschrieben (s.u.). - -So übersetzen wir es: - -* »the bionic« → »das Bionik« -* »the bionics« → »die Bioniken« - -»bionic« wird auch manchmal als Adjektiv eingesetzt: - -* »bionic« → »bionics« - - -Aus der englischsprachigen Wikipedia: - Bionics (also known as biomimicry, biomimetics, bio-inspiration, biognosis, and close to bionical creativity engineering) is the application of biological methods and systems found in nature to the study and design of engineering systems and modern technology - -Aus der deutschsprachigen Wikipedia: - Die Bionik (auch Biomimikry, Biomimetik oder Biomimese) beschäftigt sich mit dem Übertragen von Phänomenen der Natur auf die Technik. diff --git a/lang/notes/ru.txt b/lang/notes/ru.txt deleted file mode 100644 index 395c43fde925..000000000000 --- a/lang/notes/ru.txt +++ /dev/null @@ -1,69 +0,0 @@ - -This file contains notes/discussion regarding translation for Russian, written in Russian. - ---------------------------------------------------------------------------------------------------- - -Специфика: ---------------------------------------------------------------------------------------------------- -Старайтесь избавляться от англицизмов. Например, "Вы вытащили руки из своих карманов" следует заменить на "Вы вытащили руки из карманов". - -После перевода перечитайте свой текст. Если по-русски он звучит странно, это повод его несколько подредактировать с сохранением изначального смысла. - -Замена слов на уменьшительно-ласкательные приветствуется, если они подходят по смыслу. Замена слов на русский сленг или придание словам большей экспрессии тоже приветствуется, если это соответствует контексту. Импровизация в рамках контекста и смысла допустима, если конечный текст выглядит лучше, чем дословный перевод. - -После многоточия, по правилам русского языка, следующее предложение начинается с большой буквы. - -Прямую речь следует писать по русским правилам, если она встречается в переводе. - -Иногда перед началом или в конце фразы стоят пробелы. Их очень плохо видно в редакторе Transifex, имейте это в виду. Особенно часто это бывает, если фраза не окончена или по смыслу имеет продолжение. Чтобы лучше видеть такие пробелы, можно зайти в настройки редактора и включить пункт "Показать пробелы". - -Также не стоит забывать про букву Ё. - -Формы множественного числа ---------------------------------------------------------------------------------------------------- -В редакторе Transifex некоторые названия предметов требуется переводить для всех форм единственного и множественного числа. В игре, в зависимости от того, сколько у вас предметов, будет отображаться название предмета в нужной форме. - -1 — единственное число (например: яблоко) -Несколько — нужно подобрать окончание так, чтобы оно соответствовало кол-ву 2-4 предмета (например: яблока) -Много — нужно подобрать окончание так, чтобы оно соответствовало кол-ву 5-бесконечность предметов (например: яблок) -Другое — простая форма множественного числа (например: яблоки) - -В разделе "Несколько", при переводе прилагательных женского рода следует отдавать предпочтение варианту: две "стиральные машины", а не две "стиральных машины". - -Что касается книг и журналов. Слово копия и выпуск можно опустить. Как правило, если книги/журналы имеют множественное число, стоит переводить так: -1: книга «Война миров» -Несколько (например, две): книги «Война миров» -Много (например, сто): книг «Война миров» -Другое: книги «Война миров» - -1: журнал «Плейбой» -Несколько (например, два): журнала «Плейбой» -Много (например, сто): журналов «Плейбой» -Другое: журналы «Плейбой» - -Иногда встречаются такие слова, которые не стоит писать в единственном или во множественном числе, например, "фисташки", "арахис" и т.д. Их надо оставлять в той форме, которая больше подходит по смыслу. - -Спецсимволы: ---------------------------------------------------------------------------------------------------- - -Спецсимволы печатаются комбинацией клавиш. Для различных операционных систем эти комбинации разные. Для ОС Windows спецсимволы набираются на цифровой клавиатуре с помощью зажатой клавиши alt. Для ОС Linux существуют комбинации с кнопкой Compose. Для Mac ОС применяется комбинации с клавишей Option. -Некоторые символы имеют свою специфику в русском языке, отличную от английского. Нужно использовать русскую интерпретацию, если это возможно. - -Стоит различать тире и дефис. Дефис ставится внутри слова, короткий, без пробелов (например: что-то, чёрно-белый и т.п.). Тире — пунктуационный знак, ставится между словами, длиннее, отделяется пробелами с обеих сторон. -Дефис: - (минус) -Тире: — WIN:(alt + 0151) LIN:(Сompose + - + --) MAC:(Option + Shift + -) - -Кавычки следует использовать ёлочки. -Открывающая кавычка: « WIN:(alt + 0171) LIN:(Сompose + < + <) MAC:(Option + \) -Закрывающая кавычка: » WIN:(alt + 0187) LIN:(Сompose + > + >) MAC:(Option + Shift + \) - -Иногда, в тексте оригинала встречаются спецсимволы "%s", "%2$d", "\n", а также цветовые теги с цифрами 1 и 2. Оставляете их как есть, подставляя по смыслу в нужное место. Стоит ставить пробелы перед и после спецсимволов, если они есть в оригинале. -\n — перенос строки (эквивалентно клавише enter в текстовом редакторе) -%2$d или %d — вместо этих символов в игре будет отображаться числовое значение -%2$s или %s — вместо этих символов в игре будет отображаться какая-либо другая строка - -Поскольку шрифт в игре моноширинный, а у некоторых еще и квадратный, стоит соблюдать следующую специфику. -Не стоит использовать три точки вместо многоточия, в игре это очень плохо выглядит. Есть свой спецсимвол. -Многоточие: … WIN:(alt + 0133) LIN:(Сompose + . + .) MAC:(Option + ;) - -Также, в английском языке для текста игры принято правило разделять предложения двумя пробелами. В русском языке такого правила нет, поэтому после точки в конце предложения должен оставаться один пробел. From b8a55df977f243ed60f5d0527f0a66586db4f975 Mon Sep 17 00:00:00 2001 From: Olanti Date: Mon, 25 Sep 2023 23:35:17 +0300 Subject: [PATCH 17/28] Fix compile error on MacOS curses (#3260) * Fix compile error on macos Cherry-picked from 3ad05f9312d60f2cc6a3a5070dd8d4fd9d2cbd0a Co-authored-by: Binrui Dong * style(autofix.ci): automated formatting --------- Co-authored-by: Binrui Dong Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- src/CMakeLists.txt | 1 - src/ncurses_def.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e1f15113d78d..843e9fef3317 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,7 +33,6 @@ add_custom_command( ${CMAKE_SOURCE_DIR}/src/version.cmake WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - # Build tiles version if requested if (TILES) setup_library(cataclysm-tiles-common) diff --git a/src/ncurses_def.cpp b/src/ncurses_def.cpp index 988487a55f00..5b7d9cfe8189 100644 --- a/src/ncurses_def.cpp +++ b/src/ncurses_def.cpp @@ -7,7 +7,9 @@ // ncurses can define some functions as macros, but we need those identifiers // to be unchanged by the preprocessor, as we use them as function names. #define NCURSES_NOMACROS +#if !defined(__APPLE__) #define NCURSES_WIDECHAR 1 +#endif #if defined(__CYGWIN__) #include #else From 1d7d3d43afc92b31dea87a8a17e5961f65a22380 Mon Sep 17 00:00:00 2001 From: Olanti Date: Mon, 25 Sep 2023 23:35:31 +0300 Subject: [PATCH 18/28] Refresh test user dir on each test run (#3259) * Refresh user dir on each run * style(autofix.ci): automated formatting --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- tests/test_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_main.cpp b/tests/test_main.cpp index b88dee64abe3..2012f88f4a73 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -99,6 +99,7 @@ static void init_global_game_state( const std::vector &mods, option_overrides_t &option_overrides, const std::string &user_dir ) { + remove_directory( user_dir ); if( !assure_dir_exist( user_dir ) ) { assert( !"Unable to make user_dir directory. Check permissions." ); } From fbcaae316d8d3719769380d46ac98d2a800bd6e7 Mon Sep 17 00:00:00 2001 From: scarf Date: Tue, 26 Sep 2023 07:46:37 +0900 Subject: [PATCH 19/28] feat: show monster immunity in description (#3254) * feat: show monster immunity in description * fix: describe bioproof only once Co-authored-by: Chaosvolt * fix: use describe_flags * perf: use string_view * style: cmake format --------- Co-authored-by: Chaosvolt --- src/monster.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/monster.cpp b/src/monster.cpp index 5911deae0ad0..d659a742a178 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -756,9 +756,9 @@ std::string monster::extended_description() const using flag_description = std::pair; const auto describe_flags = [this, &ss]( - const std::string & format, - const std::vector &flags_names, - const std::string &if_empty = "" ) { + std::string_view format, + const std::vector &&flags_names, + std::string_view if_empty = "" ) { std::string flag_descriptions = enumerate_as_string( flags_names.begin(), flags_names.end(), [this]( const flag_description & fd ) { return type->has_flag( fd.first ) ? fd.second : ""; @@ -766,15 +766,16 @@ std::string monster::extended_description() const if( !flag_descriptions.empty() ) { ss += string_format( format, flag_descriptions ) + "\n"; } else if( !if_empty.empty() ) { - ss += if_empty + "\n"; + ss += if_empty; + ss += "\n"; } }; using property_description = std::pair; const auto describe_properties = [&ss]( - const std::string & format, + std::string_view format, const std::vector &property_names, - const std::string &if_empty = "" ) { + std::string_view if_empty = "" ) { std::string property_descriptions = enumerate_as_string( property_names.begin(), property_names.end(), []( const property_description & pd ) { return pd.first ? pd.second : ""; @@ -782,7 +783,8 @@ std::string monster::extended_description() const if( !property_descriptions.empty() ) { ss += string_format( format, property_descriptions ) + "\n"; } else if( !if_empty.empty() ) { - ss += if_empty + "\n"; + ss += if_empty; + ss += "\n"; } }; @@ -792,6 +794,15 @@ std::string monster::extended_description() const {m_flag::MF_SMELLS, pgettext( "Smell as sense", "smell" )}, }, _( "It doesn't have senses." ) ); + describe_flags( _( "It is immune to %s." ), { + {m_flag::MF_FIREPROOF, pgettext( "Fire as immunity", "fire" )}, + {m_flag::MF_COLDPROOF, pgettext( "Cold as immunity", "cold" )}, + {m_flag::MF_ACIDPROOF, pgettext( "Acid as immunity", "acid" )}, + {m_flag::MF_STUN_IMMUNE, pgettext( "Stun as immunity", "stun" )}, + {m_flag::MF_SLUDGEPROOF, pgettext( "Sludge as immunity", "sludge" )}, + {m_flag::MF_BIOPROOF, pgettext( "Biological hazards as immunity", "biohazards" )}, + } ); + describe_properties( _( "It can %s." ), { {swims(), pgettext( "Swim as an action", "swim" )}, {flies(), pgettext( "Fly as an action", "fly" )}, From 87a04bcc4a7233c554e8faa5f043e386f77d460a Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 25 Sep 2023 18:03:48 -0500 Subject: [PATCH 20/28] Allow filling containers directly from blood draw kit (#3262) --- src/iuse.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/iuse.cpp b/src/iuse.cpp index a504a2d41b32..14f781d0b56e 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -4592,7 +4592,6 @@ int iuse::blood_draw( player *p, item *it, bool, const tripoint & ) if( acid_blood ) { item acid( "acid", calendar::turn ); - it->put_in( acid ); if( one_in( 3 ) ) { if( it->inc_damage( DT_ACID ) ) { p->add_msg_if_player( m_info, _( "…but acidic blood melts the %s, destroying it!" ), @@ -4602,6 +4601,9 @@ int iuse::blood_draw( player *p, item *it, bool, const tripoint & ) } p->add_msg_if_player( m_info, _( "…but acidic blood damages the %s!" ), it->tname() ); } + if( !liquid_handler::handle_liquid( acid, nullptr, 1, nullptr ) ) { + it->put_in( acid ); + } return it->type->charges_to_use(); } @@ -4609,7 +4611,9 @@ int iuse::blood_draw( player *p, item *it, bool, const tripoint & ) return it->type->charges_to_use(); } - it->put_in( blood ); + if( !liquid_handler::handle_liquid( blood, nullptr, 1, nullptr ) ) { + it->put_in( blood ); + } return it->type->charges_to_use(); } From dc43e2353558aa36352b76e0b4b3d577915d6272 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Mon, 25 Sep 2023 23:41:55 -0500 Subject: [PATCH 21/28] Streamline has_trait_flag behavior (#2911) * Streamline has_trait_flag behavior * Start work on it * Update type_id.h * Update the thing * Commit latest fixes * Update flag_trait.h * Commit what I have for now * style(autofix.ci): automated formatting * Update condition.cpp * And that should be the basics of the code * style(autofix.ci): automated formatting * Start up the JSON work next * Update flags_mutation.json * Update JSON_FLAGS.md * style(autofix.ci): automated formatting * Update flags_mutation.json * Update string_id_null_ids.cpp * Apply suggestions from code review Co-authored-by: Olanti * Do some of the suggested things * Work on part of the requests * Add the validation thingy * refactor: extract `trait_flag_str_id` for `PRED` * refactor: remove `conflicts` usage Co-authored-by: olanti-p * refactor: extract other trait flag ids Co-authored-by: olanti-p * style(autofix.ci): automated formatting --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Olanti Co-authored-by: scarf --- data/json/flags.json | 6 - data/json/flags_mutation.json | 132 ++++++++++++++++++ data/json/obsoletion/mutations.json | 1 - .../docs/en/mod/json/reference/json_flags.md | 33 ++++- src/activity_handlers.cpp | 6 +- src/character.cpp | 35 +++-- src/character.h | 2 +- src/condition.cpp | 13 +- src/consumption.cpp | 4 +- src/flag_trait.cpp | 116 +++++++++++++++ src/flag_trait.h | 56 ++++++++ src/init.cpp | 5 + src/item.cpp | 2 +- src/iuse_actor.cpp | 13 +- src/magic.cpp | 7 +- src/melee.cpp | 15 +- src/mondeath.cpp | 17 ++- src/mutation.cpp | 8 +- src/mutation.h | 2 +- src/mutation_data.cpp | 7 +- src/string_id_null_ids.cpp | 1 + src/type_id.h | 4 + 22 files changed, 430 insertions(+), 55 deletions(-) create mode 100644 data/json/flags_mutation.json create mode 100644 src/flag_trait.cpp create mode 100644 src/flag_trait.h diff --git a/data/json/flags.json b/data/json/flags.json index 99b5ffda108e..f76a71b5b3b3 100644 --- a/data/json/flags.json +++ b/data/json/flags.json @@ -1047,12 +1047,6 @@ "context": [ "SPELL" ], "//": "pain altering spells can't be resisted (like with the deadened trait)" }, - { - "id": "NON_THRESH", - "type": "json_flag", - "context": [ "mutation" ], - "//": "This mutation does not count toward thresholds at all." - }, { "id": "EFFECT_FEATHER_FALL", "context": [ ], diff --git a/data/json/flags_mutation.json b/data/json/flags_mutation.json new file mode 100644 index 000000000000..b2ec7e307c83 --- /dev/null +++ b/data/json/flags_mutation.json @@ -0,0 +1,132 @@ +[ + { + "id": "BG_SURVIVAL_STORY", + "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "CANNIBAL", + "type": "mutation_flag" + }, + { + "id": "hair_black", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_blond", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_brown", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_crewcut", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_fro", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_gray", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_long", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_medium", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_mohawk", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_red", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_short", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "hair_white", + "//": "This trait flag is used by cosmetic trait JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "mycus", + "//": "This trait flag is used in dialogue JSON, with no hardcode usage at present.", + "type": "mutation_flag" + }, + { + "id": "MUTATION_THRESHOLD", + "type": "mutation_flag" + }, + { + "id": "NEED_ACTIVE_TO_MELEE", + "type": "mutation_flag" + }, + { + "id": "NO_THIRST", + "type": "mutation_flag" + }, + { + "id": "NO_RADIATION", + "type": "mutation_flag" + }, + { + "id": "NON_THRESH", + "type": "mutation_flag" + }, + { + "id": "PSYCHOPATH", + "type": "mutation_flag" + }, + { + "id": "PRED1", + "type": "mutation_flag" + }, + { + "id": "PRED2", + "type": "mutation_flag" + }, + { + "id": "PRED3", + "type": "mutation_flag" + }, + { + "id": "PRED4", + "type": "mutation_flag" + }, + { + "id": "SAPIOVORE", + "type": "mutation_flag" + }, + { + "id": "SILENT_SPELL", + "type": "mutation_flag" + }, + { + "id": "SUBTLE_SPELL", + "type": "mutation_flag" + }, + { + "id": "UNARMED_BONUS", + "type": "mutation_flag" + } +] diff --git a/data/json/obsoletion/mutations.json b/data/json/obsoletion/mutations.json index 94c1dbf5ae74..12c5621cc777 100644 --- a/data/json/obsoletion/mutations.json +++ b/data/json/obsoletion/mutations.json @@ -130,7 +130,6 @@ "points": 2, "description": "Your body is simply immune to diseases. You will never catch an ambient disease.", "prereqs": [ "DISRESISTANT" ], - "flags": [ "NO_DISEASE" ], "valid": false }, { diff --git a/doc/src/content/docs/en/mod/json/reference/json_flags.md b/doc/src/content/docs/en/mod/json/reference/json_flags.md index 1e0febf26281..4bfc8647e892 100644 --- a/doc/src/content/docs/en/mod/json/reference/json_flags.md +++ b/doc/src/content/docs/en/mod/json/reference/json_flags.md @@ -1178,10 +1178,41 @@ example, impale and scratch. ## Mutations -#### Flags +#### Mutation Flags + +Mutation flags use a different JSON type from other flags, see json/flags_mutation.json. Primary +difference is that `conflicts` and `requires` are the only additional properties that can be added +to them. + +The following show all trait flags that are currently used by the game's code. Trait flags must also +be defined in JSON if they are to be used in NPC dialogue conditions. +- `CANNIBAL` No morale penalty from butchery human corpses, skips warning you about human meat. + NOTE: this only skips the warning, the actual morale effects of eating human flesh still require + one of the relevant traits. Custom traits with this flag will skip the warning and suffer the + morale penalty. +- `NEED_ACTIVE_TO_MELEE` A mutation with this flag will only provide unarmed bonuses if it's been + toggled on. - `NO_RADIATION` This mutation grants immunity to radiations. - `NO_THIRST` Your thirst is not modified by food or drinks. +- `NON_THRESH` Mutations with this flag will not count towards the mutation strength (and thus + ability to breach a mutation threshold) of any categories it counts as belonging to. +- `PRED1` Reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing + monsters with the `GUILT` flag. +- `PRED2` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is + enabled), reduces morale impact of enzlaving zombie corpses, reduces morale impact of killing + monsters with the `GUILT` flag. +- `PRED3` Increases EXP gain from combat, negates skill rust of combat skills (if skill rust is + enabled), increases tolerance for enzlaving zombies while already depressed, negates morale impact + of killing monsters with the `GUILT` flag. +- `PRED4` Increases EXP gain from combat, prevents EXP gain from combat from affecting focus, + negates skill rust of combat skills (if skill rust is enabled), negates morale impact of enzlaving + zombie corpses, increases tolerance for enzlaving zombies while already depressed, negates morale + impact of killing monsters with the `GUILT` flag. +- `PSYCHOPATH` No morale penalty from butchering human corpses. +- `SAPIVORE` No morale penalty from butcheing human corpses. +- `SILENT_SPELL` Negates the negative impact of mouth encumbrance on spells with the `VERBAL` flag. +- `SUBTLE_SPELL` Negates the negative impact of arm encumbrance on spells with the `SOMATIC` flag. - `UNARMED_BONUS` You get a bonus to unarmed bash and cut damage equal to unarmed_skill/2 up to 4. ### Categories diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 79223276899c..97298f707999 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -247,9 +247,9 @@ static const quality_id qual_LOCKPICK( "LOCKPICK" ); static const species_id HUMAN( "HUMAN" ); static const species_id ZOMBIE( "ZOMBIE" ); -static const std::string trait_flag_CANNIBAL( "CANNIBAL" ); -static const std::string trait_flag_PSYCHOPATH( "PSYCHOPATH" ); -static const std::string trait_flag_SAPIOVORE( "SAPIOVORE" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); +static const trait_flag_str_id trait_flag_PSYCHOPATH( "PSYCHOPATH" ); +static const trait_flag_str_id trait_flag_SAPIOVORE( "SAPIOVORE" ); static const bionic_id bio_ears( "bio_ears" ); static const bionic_id bio_painkiller( "bio_painkiller" ); diff --git a/src/character.cpp b/src/character.cpp index 761e0785f444..9d6b3c5debd7 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -378,6 +378,15 @@ static const flag_str_id flag_BIONIC_ARMOR_INTERFACE( "BIONIC_ARMOR_INTERFACE" ) static const mtype_id mon_player_blob( "mon_player_blob" ); static const mtype_id mon_shadow_snake( "mon_shadow_snake" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + +static const trait_flag_str_id flag_NO_THIRST( "NO_THIRST" ); +static const trait_flag_str_id flag_NO_RADIATION( "NO_RADIATION" ); +static const trait_flag_str_id flag_NON_THRESH( "NON_THRESH" ); + namespace io { @@ -3446,16 +3455,16 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress amount = 0; } } - if( has_trait_flag( "PRED2" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED2 ) && skill.is_combat_skill() ) { if( one_in( 3 ) ) { amount *= 2; } } - if( has_trait_flag( "PRED3" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED3 ) && skill.is_combat_skill() ) { amount *= 2; } - if( has_trait_flag( "PRED4" ) && skill.is_combat_skill() ) { + if( has_trait_flag( trait_flag_PRED4 ) && skill.is_combat_skill() ) { amount *= 3; } @@ -3489,8 +3498,9 @@ void Character::practice( const skill_id &id, int amount, int cap, bool suppress focus_pool -= chance_to_drop / 100; // Apex Predators don't think about much other than killing. // They don't lose Focus when practicing combat skills. - if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && ( !( has_trait_flag( "PRED4" ) && - skill.is_combat_skill() ) ) ) { + if( ( rng( 1, 100 ) <= ( chance_to_drop % 100 ) ) && + ( !( has_trait_flag( trait_flag_PRED4 ) && + skill.is_combat_skill() ) ) ) { focus_pool--; } } @@ -3600,17 +3610,14 @@ void Character::apply_skill_boost() void Character::do_skill_rust() { const int rust_rate_tmp = rust_rate(); - static const std::string PRED2( "PRED2" ); - static const std::string PRED3( "PRED3" ); - static const std::string PRED4( "PRED4" ); for( std::pair &pair : *_skills ) { const Skill &aSkill = *pair.first; SkillLevel &skill_level_obj = pair.second; if( aSkill.is_combat_skill() && - ( ( has_trait_flag( PRED2 ) && calendar::once_every( 8_hours ) ) || - ( has_trait_flag( PRED3 ) && calendar::once_every( 4_hours ) ) || - ( has_trait_flag( PRED4 ) && calendar::once_every( 3_hours ) ) ) ) { + ( ( has_trait_flag( trait_flag_PRED2 ) && calendar::once_every( 8_hours ) ) || + ( has_trait_flag( trait_flag_PRED3 ) && calendar::once_every( 4_hours ) ) || + ( has_trait_flag( trait_flag_PRED4 ) && calendar::once_every( 3_hours ) ) ) ) { // Their brain is optimized to remember this if( one_in( 13 ) ) { // They've already passed the roll to avoid rust at @@ -4438,7 +4445,7 @@ std::pair Character::get_fatigue_description() const void Character::mod_thirst( int nthirst ) { - if( has_trait_flag( "NO_THIRST" ) ) { + if( has_trait_flag( flag_NO_THIRST ) ) { return; } set_thirst( std::max( -100, thirst + nthirst ) ); @@ -7084,7 +7091,7 @@ void Character::set_rad( int new_rad ) void Character::mod_rad( int mod ) { - if( has_trait_flag( "NO_RADIATION" ) ) { + if( has_trait_flag( flag_NO_RADIATION ) ) { return; } set_rad( std::max( 0, get_rad() + mod ) ); @@ -7810,7 +7817,7 @@ void Character::set_highest_cat_level() // Then use the map to set the category levels for( const std::pair &i : dependency_map ) { const mutation_branch &mdata = i.first.obj(); - if( !mdata.flags.count( "NON_THRESH" ) ) { + if( !mdata.flags.count( flag_NON_THRESH ) ) { for( const std::string &cat : mdata.category ) { // Decay category strength based on how far it is from the current mutation mutation_category_level[cat] += 8 / static_cast( std::pow( 2, i.second ) ); diff --git a/src/character.h b/src/character.h index a84bf824865c..07214353d534 100644 --- a/src/character.h +++ b/src/character.h @@ -703,7 +703,7 @@ class Character : public Creature, public visitable /** Returns true if the player has the entered starting trait */ bool has_base_trait( const trait_id &b ) const; /** Returns true if player has a trait with a flag */ - bool has_trait_flag( const std::string &b ) const; + bool has_trait_flag( const trait_flag_str_id &b ) const; /** Returns true if character has a trait which cancels the entered trait. */ bool has_opposite_trait( const trait_id &flag ) const; diff --git a/src/condition.cpp b/src/condition.cpp index acac62bf6005..dc0b64503bb7 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -46,7 +46,7 @@ class basecamp; class recipe; static const efftype_id effect_currently_busy( "currently_busy" ); - +static const trait_flag_str_id flag_MUTATION_THRESHOLD( "MUTATION_THRESHOLD" ); // throws an error on failure, so no need to return std::string get_talk_varname( const JsonObject &jo, const std::string &member, bool check_value ) { @@ -126,13 +126,18 @@ template void conditional_t::set_has_trait_flag( const JsonObject &jo, const std::string &member, bool is_npc ) { - const std::string &trait_flag_to_check = jo.get_string( member ); - condition = [trait_flag_to_check, is_npc]( const T & d ) { + const std::string &raw = jo.get_string( member ); + const trait_flag_str_id trait_flag_to_check( raw ); + if( !trait_flag_to_check.is_valid() ) { + jo.show_warning( string_format( "Invalid trait flag %s", raw ), member ); + } + const bool check_threshold = trait_flag_to_check == flag_MUTATION_THRESHOLD; + condition = [trait_flag_to_check, check_threshold, is_npc]( const T & d ) { player *actor = d.alpha; if( is_npc ) { actor = dynamic_cast( d.beta ); } - if( trait_flag_to_check == "MUTATION_THRESHOLD" ) { + if( check_threshold ) { return actor->crossed_threshold(); } return actor->has_trait_flag( trait_flag_to_check ); diff --git a/src/consumption.cpp b/src/consumption.cpp index 344bdcda4f13..285a7ba6d40b 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -118,6 +118,8 @@ static const trait_id trait_THRESH_URSINE( "THRESH_URSINE" ); static const trait_id trait_VEGETARIAN( "VEGETARIAN" ); static const trait_id trait_WATERSLEEP( "WATERSLEEP" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); + static const std::string flag_HIDDEN_HALLU( "HIDDEN_HALLU" ); static const std::string flag_ALLERGEN_EGG( "ALLERGEN_EGG" ); static const std::string flag_ALLERGEN_FRUIT( "ALLERGEN_FRUIT" ); @@ -755,7 +757,7 @@ ret_val Character::will_eat( const item &food, bool interactive ) } const bool carnivore = has_trait( trait_CARNIVORE ); - if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( "CANNIBAL" ) ) { + if( food.has_flag( flag_CANNIBALISM ) && !has_trait_flag( trait_flag_CANNIBAL ) ) { add_consequence( _( "The thought of eating human flesh makes you feel sick." ), edible_rating::cannibalism ); } diff --git a/src/flag_trait.cpp b/src/flag_trait.cpp new file mode 100644 index 000000000000..9824feab956b --- /dev/null +++ b/src/flag_trait.cpp @@ -0,0 +1,116 @@ +#include + +#include "debug.h" +#include "flag_trait.h" +#include "json.h" +#include "type_id.h" +#include "generic_factory.h" + +namespace +{ +generic_factory json_trait_flags_all( "json_trait_flags" ); +} // namespace + +/** @relates int_id */ +template<> +bool trait_flag_id ::is_valid() const +{ + return json_trait_flags_all.is_valid( *this ); +} + +/** @relates int_id */ +template<> +const json_trait_flag &trait_flag_id::obj() const +{ + return json_trait_flags_all.obj( *this ); +} + +/** @relates int_id */ +template<> +const trait_flag_str_id &trait_flag_id::id() const +{ + return json_trait_flags_all.convert( *this ); +} + +/** @relates string_id */ +template<> +bool trait_flag_str_id ::is_valid() const +{ + return json_trait_flags_all.is_valid( *this ); +} + +/** @relates string_id */ +template<> +const json_trait_flag &trait_flag_str_id::obj() const +{ + return json_trait_flags_all.obj( *this ); +} + +/** @relates string_id */ +template<> +trait_flag_id trait_flag_str_id::id() const +{ + return json_trait_flags_all.convert( *this, trait_flag_id( -1 ) ); +} + +/** @relates int_id */ +template<> +trait_flag_id::int_id( const trait_flag_str_id &id ) : _id( id.id() ) +{ +} + +json_trait_flag::operator bool() const +{ + return id.is_valid(); +} + +const json_trait_flag &json_trait_flag::get( const std::string &id ) +{ + static const json_trait_flag null_value = json_trait_flag(); + const trait_flag_str_id f_id( id ); + return f_id.is_valid() ? *f_id : null_value; +} + +void json_trait_flag::load( const JsonObject &, const std::string & ) +{ +} + +void json_trait_flag::check_consistency() +{ + json_trait_flags_all.check(); +} + +void json_trait_flag::reset() +{ + json_trait_flags_all.reset(); +} + +void json_trait_flag::load_all( const JsonObject &jo, const std::string &src ) +{ + json_trait_flags_all.load( jo, src ); +} + +void json_trait_flag::check() const +{ + for( const auto &conflicting : conflicts_ ) { + if( !trait_flag_str_id( conflicting ).is_valid() ) { + debugmsg( "trait flag definition %s specifies unknown conflicting field %s", id.str(), + conflicting ); + } + } +} + +void json_trait_flag::finalize_all() +{ + json_trait_flags_all.finalize(); +} + +bool json_trait_flag::is_ready() +{ + return !json_trait_flags_all.empty(); +} + +const std::vector &json_trait_flag::get_all() +{ + return json_trait_flags_all.get_all(); +} diff --git a/src/flag_trait.h b/src/flag_trait.h new file mode 100644 index 000000000000..68cb479f6ef1 --- /dev/null +++ b/src/flag_trait.h @@ -0,0 +1,56 @@ +#pragma once +#ifndef CATA_SRC_FLAG_TRAIT_H +#define CATA_SRC_FLAG_TRAIT_H + +#include +#include + +#include "type_id.h" + +class JsonObject; + +class json_trait_flag +{ + friend class DynamicDataLoader; + friend class generic_factory; + + public: + // used by generic_factory + trait_flag_str_id id = trait_flag_str_id::NULL_ID(); + bool was_loaded = false; + + json_trait_flag() = default; + + /** Fetches flag definition (or null flag if not found) */ + static const json_trait_flag &get( const std::string &id ); + + /** Is this a valid (non-null) flag */ + operator bool() const; + + void check() const; + + /** true, if flags were loaded */ + static bool is_ready(); + + static const std::vector &get_all(); + + private: + std::set conflicts_; + + /** Load flag definition from JSON (NO-OP) */ + void load( const JsonObject &jo, const std::string &src ); + + /** Load all flags from JSON */ + static void load_all( const JsonObject &jo, const std::string &src ); + + /** finalize */ + static void finalize_all( ); + + /** Check consistency of all loaded flags */ + static void check_consistency(); + + /** Clear all loaded flags (invalidating any pointers) */ + static void reset(); +}; + +#endif // CATA_SRC_FLAG_TRAIT_H diff --git a/src/init.cpp b/src/init.cpp index c6832eb379cb..a62f6320c4ec 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -45,6 +45,7 @@ #include "filesystem.h" #include "fstream_utils.h" #include "flag.h" +#include "flag_trait.h" #include "gates.h" #include "harvest.h" #include "item_action.h" @@ -249,6 +250,7 @@ void DynamicDataLoader::initialize() add( "WORLD_OPTION", &load_world_option ); add( "EXTERNAL_OPTION", &load_external_option ); add( "json_flag", &json_flag::load_all ); + add( "mutation_flag", &json_trait_flag::load_all ); add( "fault", &fault::load_fault ); add( "field_type", &field_types::load ); add( "weather_type", &weather_types::load ); @@ -570,6 +572,7 @@ void DynamicDataLoader::unload_data() item_action_generator::generator().reset(); item_controller->reset(); json_flag::reset(); + json_trait_flag::reset(); MapExtras::reset(); mapgen_palette::reset(); materials::reset(); @@ -652,6 +655,7 @@ void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) using named_entry = std::pair>; const std::vector entries = {{ { _( "Flags" ), &json_flag::finalize_all }, + { _( "Mutation Flags" ), &json_trait_flag::finalize_all }, { _( "Body parts" ), &body_part_type::finalize_all }, { _( "Bionics" ), &bionic_data::finalize_all }, { _( "Weather types" ), &weather_types::finalize_all }, @@ -729,6 +733,7 @@ void DynamicDataLoader::check_consistency( loading_ui &ui ) using named_entry = std::pair>; const std::vector entries = {{ { _( "Flags" ), &json_flag::check_consistency }, + { _( "Mutation Flags" ), &json_trait_flag::check_consistency }, { _( "Crafting requirements" ), []() { diff --git a/src/item.cpp b/src/item.cpp index 89618c6a05f7..effb3c1d323b 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -158,7 +158,7 @@ static const quality_id qual_JACK( "JACK" ); static const quality_id qual_LIFT( "LIFT" ); static const species_id ROBOT( "ROBOT" ); -static const std::string trait_flag_CANNIBAL( "CANNIBAL" ); +static const trait_flag_str_id trait_flag_CANNIBAL( "CANNIBAL" ); static const bionic_id bio_digestion( "bio_digestion" ); diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 4e38999390c5..e7410146cdc3 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -152,6 +152,11 @@ static const std::string flag_UNDERSIZE( "UNDERSIZE" ); static const std::string flag_VARSIZE( "VARSIZE" ); static const std::string flag_POWERARMOR_MOD( "POWERARMOR_MOD" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + class npc; std::unique_ptr iuse_transform::clone() const @@ -2091,9 +2096,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const int tolerance_level = 9; if( p.has_trait( trait_PSYCHOPATH ) || p.has_trait( trait_SAPIOVORE ) ) { tolerance_level = 0; - } else if( p.has_trait_flag( "PRED4" ) ) { + } else if( p.has_trait_flag( trait_flag_PRED4 ) ) { tolerance_level = 5; - } else if( p.has_trait_flag( "PRED3" ) ) { + } else if( p.has_trait_flag( trait_flag_PRED3 ) ) { tolerance_level = 7; } @@ -2137,9 +2142,9 @@ int enzlave_actor::use( player &p, item &it, bool t, const tripoint & ) const if( p.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; maxMalus *= 3; - } else if( p.has_trait_flag( "PRED1" ) ) { + } else if( p.has_trait_flag( trait_flag_PRED1 ) ) { moraleMalus /= 4; - } else if( p.has_trait_flag( "PRED2" ) ) { + } else if( p.has_trait_flag( trait_flag_PRED2 ) ) { moraleMalus /= 5; } diff --git a/src/magic.cpp b/src/magic.cpp index 7815169c505f..172b9480cdb8 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -48,6 +48,8 @@ #include "units.h" static const trait_id trait_NONE( "NONE" ); +static const trait_flag_str_id trait_flag_SUBTLE_SPELL( "SUBTLE_SPELL" ); +static const trait_flag_str_id trait_flag_SILENT_SPELL( "SILENT_SPELL" ); namespace io { @@ -758,13 +760,14 @@ float spell::spell_fail( const Character &guy ) const return 1.0f; } float fail_chance = std::pow( ( effective_skill - 30.0f ) / 30.0f, 2 ); - if( has_flag( spell_flag::SOMATIC ) && !guy.has_trait_flag( "SUBTLE_SPELL" ) ) { + if( has_flag( spell_flag::SOMATIC ) && + !guy.has_trait_flag( trait_flag_SUBTLE_SPELL ) ) { // the first 20 points of encumbrance combined is ignored const int arms_encumb = std::max( 0, guy.encumb( bp_arm_l ) + guy.encumb( bp_arm_r ) - 20 ); // each encumbrance point beyond the "gray" color counts as half an additional fail % fail_chance += arms_encumb / 200.0f; } - if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( "SILENT_SPELL" ) ) { + if( has_flag( spell_flag::VERBAL ) && !guy.has_trait_flag( trait_flag_SILENT_SPELL ) ) { // a little bit of mouth encumbrance is allowed, but not much const int mouth_encumb = std::max( 0, guy.encumb( bp_mouth ) - 5 ); fail_chance += mouth_encumb / 100.0f; diff --git a/src/melee.cpp b/src/melee.cpp index 68e22c7c3d8f..d4aab29e3949 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -113,6 +113,9 @@ static const trait_id trait_PROF_SKATER( "PROF_SKATER" ); static const trait_id trait_VINES2( "VINES2" ); static const trait_id trait_VINES3( "VINES3" ); +static const trait_flag_str_id trait_flag_NEED_ACTIVE_TO_MELEE( "NEED_ACTIVE_TO_MELEE" ); +static const trait_flag_str_id trait_flag_UNARMED_BONUS( "UNARMED_BONUS" ); + static const efftype_id effect_amigara( "amigara" ); static const species_id HUMAN( "HUMAN" ); @@ -966,12 +969,13 @@ void Character::roll_bash_damage( bool crit, damage_instance &di, bool average, if( left_empty || right_empty ) { float per_hand = 0.0f; for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( "NEED_ACTIVE_TO_MELEE" ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_NEED_ACTIVE_TO_MELEE ) > 0 && + !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int bash_bonus = mut->bash_dmg_bonus; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && bash_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && bash_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += bash_bonus + unarmed_bonus; @@ -1054,12 +1058,13 @@ void Character::roll_cut_damage( bool crit, damage_instance &di, bool average, } for( const trait_id &mut : get_mutations() ) { - if( mut->flags.count( "NEED_ACTIVE_TO_MELEE" ) > 0 && !has_active_mutation( mut ) ) { + if( mut->flags.count( trait_flag_NEED_ACTIVE_TO_MELEE ) > 0 && + !has_active_mutation( mut ) ) { continue; } float unarmed_bonus = 0.0f; const int cut_bonus = mut->cut_dmg_bonus; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && cut_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && cut_bonus > 0 ) { unarmed_bonus += std::min( get_skill_level( skill_unarmed ) / 2, 4 ); } per_hand += cut_bonus + unarmed_bonus; @@ -1126,7 +1131,7 @@ void Character::roll_stab_damage( bool crit, damage_instance &di, bool /*average for( const trait_id &mut : get_mutations() ) { int stab_bonus = mut->pierce_dmg_bonus; int unarmed_bonus = 0; - if( mut->flags.count( "UNARMED_BONUS" ) > 0 && stab_bonus > 0 ) { + if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 && stab_bonus > 0 ) { unarmed_bonus = std::min( unarmed_skill / 2, 4 ); } diff --git a/src/mondeath.cpp b/src/mondeath.cpp index 4b4ebc740618..218602eb43ac 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -85,6 +85,11 @@ static const trait_id trait_KILLER( "KILLER" ); static const trait_id trait_PACIFIST( "PACIFIST" ); static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); +static const trait_flag_str_id trait_flag_PRED1( "PRED1" ); +static const trait_flag_str_id trait_flag_PRED2( "PRED2" ); +static const trait_flag_str_id trait_flag_PRED3( "PRED3" ); +static const trait_flag_str_id trait_flag_PRED4( "PRED4" ); + void mdeath::normal( monster &z ) { if( z.no_corpse_quiet ) { @@ -438,8 +443,8 @@ void mdeath::guilt( monster &z ) guilt_tresholds[50] = _( "You regret killing %s." ); guilt_tresholds[25] = _( "You feel remorse for killing %s." ); - if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( "PRED3" ) || - g->u.has_trait_flag( "PRED4" ) || g->u.has_trait( trait_KILLER ) ) { + if( g->u.has_trait( trait_PSYCHOPATH ) || g->u.has_trait_flag( trait_flag_PRED3 ) || + g->u.has_trait_flag( trait_flag_PRED4 ) || g->u.has_trait( trait_KILLER ) ) { return; } if( rl_dist( z.pos(), g->u.pos() ) > MAX_GUILT_DISTANCE ) { @@ -458,7 +463,9 @@ void mdeath::guilt( monster &z ) "about their deaths anymore." ), z.name( maxKills ) ); } return; - } else if( ( g->u.has_trait_flag( "PRED1" ) ) || ( g->u.has_trait_flag( "PRED2" ) ) ) { + + } else if( ( g->u.has_trait_flag( trait_flag_PRED1 ) ) || + ( g->u.has_trait_flag( trait_flag_PRED1 ) ) ) { msg = ( _( "Culling the weak is distasteful, but necessary." ) ); msgtype = m_neutral; } else { @@ -481,9 +488,9 @@ void mdeath::guilt( monster &z ) moraleMalus /= 10; if( g->u.has_trait( trait_PACIFIST ) ) { moraleMalus *= 5; - } else if( g->u.has_trait_flag( "PRED1" ) ) { + } else if( g->u.has_trait_flag( trait_flag_PRED1 ) ) { moraleMalus /= 4; - } else if( g->u.has_trait_flag( "PRED2" ) ) { + } else if( g->u.has_trait_flag( trait_flag_PRED2 ) ) { moraleMalus /= 5; } } diff --git a/src/mutation.cpp b/src/mutation.cpp index 5173ce56e98c..a9d044dd5943 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -103,12 +103,10 @@ bool Character::has_trait( const trait_id &b ) const return my_mutations.count( b ) || enchantment_cache->get_mutations().count( b ); } -bool Character::has_trait_flag( const std::string &b ) const +bool Character::has_trait_flag( const trait_flag_str_id &b ) const { - // UGLY, SLOW, should be cached as my_mutation_flags or something - for( const trait_id &mut : get_mutations() ) { - const mutation_branch &mut_data = mut.obj(); - if( mut_data.flags.count( b ) > 0 ) { + for( const mutation_branch *mut : cached_mutations ) { + if( mut->flags.count( b ) > 0 ) { return true; } } diff --git a/src/mutation.h b/src/mutation.h index 8fe226d47b5e..d25deea6ba26 100644 --- a/src/mutation.h +++ b/src/mutation.h @@ -265,7 +265,7 @@ struct mutation_branch { std::vector replacements; // Mutations that replace this one std::vector additions; // Mutations that add to this one std::vector category; // Mutation Categories - std::set flags; // Mutation flags + std::set flags; // Mutation flags std::map protection; // Mutation wet effects std::map encumbrance_always; // Mutation encumbrance that always applies // Mutation encumbrance that applies when covered with unfitting item diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index a070de723d85..994ec211643a 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -455,7 +455,7 @@ void mutation_branch::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "cancels", cancels, trait_reader{} ); optional( jo, was_loaded, "changes_to", replacements, trait_reader{} ); optional( jo, was_loaded, "leads_to", additions, trait_reader{} ); - optional( jo, was_loaded, "flags", flags, string_reader{} ); + optional( jo, was_loaded, "flags", flags, auto_flags_reader {} ); optional( jo, was_loaded, "types", types, string_reader{} ); optional( jo, was_loaded, "enchantments", enchantments ); @@ -609,6 +609,11 @@ void mutation_branch::check_consistency() for( const enchantment_id &ench : mdata.enchantments ) { ench->check(); } + for( const auto &flag : mdata.flags ) { + if( !flag.is_valid() ) { + debugmsg( "mutation %s refers to undefined mutation flag %s", mid, flag ); + } + } ::check_consistency( mdata.prereqs, mid, "prereq" ); ::check_consistency( mdata.prereqs2, mid, "prereqs2" ); ::check_consistency( mdata.threshreq, mid, "threshreq" ); diff --git a/src/string_id_null_ids.cpp b/src/string_id_null_ids.cpp index f58922822d49..f272078e8bd4 100644 --- a/src/string_id_null_ids.cpp +++ b/src/string_id_null_ids.cpp @@ -32,6 +32,7 @@ MAKE_NULL_ID( recipe, "null" ) MAKE_NULL_ID( translation, "null" ) MAKE_NULL_ID( Item_group, "" ) MAKE_NULL_ID( morale_type_data, "" ) +MAKE_NULL_ID( json_trait_flag, "null" ) #define MAKE_NULL_ID2( type, ... ) \ struct type; \ diff --git a/src/type_id.h b/src/type_id.h index fed78f471067..fae447247343 100644 --- a/src/type_id.h +++ b/src/type_id.h @@ -212,4 +212,8 @@ class json_flag; using flag_id = int_id; using flag_str_id = string_id; +class json_trait_flag; +using trait_flag_id = int_id; +using trait_flag_str_id = string_id; + #endif // CATA_SRC_TYPE_ID_H From 897c78f703ccccf69b6353c1b78a6cca32fbb4cb Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Tue, 26 Sep 2023 03:27:59 -0500 Subject: [PATCH 22/28] Add more grid battery options (#3264) --- data/json/construction.json | 56 +++++++++++++ data/json/construction_group.json | 20 +++++ .../furniture-appliances.json | 81 +++++++++++++++++++ 3 files changed, 157 insertions(+) diff --git a/data/json/construction.json b/data/json/construction.json index c0a0d190b41f..75e4a453cfd3 100644 --- a/data/json/construction.json +++ b/data/json/construction.json @@ -4200,6 +4200,62 @@ "pre_special": "check_empty", "post_furniture": "f_battery_huge" }, + { + "type": "construction", + "id": "constr_battery_small", + "group": "install_small_battery", + "category": "WORKSHOP", + "required_skills": [ [ "fabrication", 3 ], [ "electronics", 1 ] ], + "time": "30 m", + "qualities": [ [ { "id": "SCREW", "level": 1 } ] ], + "using": [ [ "soldering_standard", 10 ] ], + "components": [ [ [ "sheet_metal_small", 4 ] ], [ [ "cable", 5 ] ], [ [ "small_storage_battery", 1 ] ] ], + "pre_note": "Will only work if constructed in a building with an electric grid.", + "pre_special": "check_empty", + "post_furniture": "f_battery_small" + }, + { + "type": "construction", + "id": "constr_battery_car", + "group": "install_car_battery", + "category": "WORKSHOP", + "required_skills": [ [ "fabrication", 3 ], [ "electronics", 1 ] ], + "time": "30 m", + "qualities": [ [ { "id": "SCREW", "level": 1 } ] ], + "using": [ [ "soldering_standard", 10 ] ], + "components": [ [ [ "sheet_metal_small", 4 ] ], [ [ "cable", 5 ] ], [ [ "battery_car", 1 ] ] ], + "pre_note": "Will only work if constructed in a building with an electric grid.", + "pre_special": "check_empty", + "post_furniture": "f_battery_car" + }, + { + "type": "construction", + "id": "constr_battery_motorbike", + "group": "install_motorbike_battery", + "category": "WORKSHOP", + "required_skills": [ [ "fabrication", 3 ], [ "electronics", 1 ] ], + "time": "30 m", + "qualities": [ [ { "id": "SCREW", "level": 1 } ] ], + "using": [ [ "soldering_standard", 10 ] ], + "components": [ [ [ "sheet_metal_small", 4 ] ], [ [ "cable", 5 ] ], [ [ "battery_motorbike", 1 ] ] ], + "pre_note": "Will only work if constructed in a building with an electric grid.", + "pre_special": "check_empty", + "post_furniture": "f_battery_motorbike" + }, + { + "type": "construction", + "id": "constr_battery_motorbike_small", + "group": "install_small_motorbike_battery", + "category": "WORKSHOP", + "required_skills": [ [ "fabrication", 3 ], [ "electronics", 1 ] ], + "time": "30 m", + "qualities": [ [ { "id": "SCREW", "level": 1 } ] ], + "using": [ [ "soldering_standard", 10 ] ], + "components": [ [ [ "sheet_metal_small", 4 ] ], [ [ "cable", 5 ] ], [ [ "battery_motorbike_small", 1 ] ] ], + "pre_note": "Will only work if constructed in a building with an electric grid.", + "pre_special": "check_empty", + "post_furniture": "f_battery_motorbike_small" + }, { "type": "construction", "id": "constr_oven", diff --git a/data/json/construction_group.json b/data/json/construction_group.json index 3449f284a381..c9c3fd6aed0c 100644 --- a/data/json/construction_group.json +++ b/data/json/construction_group.json @@ -964,6 +964,26 @@ "id": "install_storage_battery", "name": "Install Storage Battery" }, + { + "type": "construction_group", + "id": "install_small_battery", + "name": "Install Small Storage Battery" + }, + { + "type": "construction_group", + "id": "install_car_battery", + "name": "Install Car Battery" + }, + { + "type": "construction_group", + "id": "install_motorbike_battery", + "name": "Install Motorbike Battery" + }, + { + "type": "construction_group", + "id": "install_small_motorbike_battery", + "name": "Install Small Motorbike Battery" + }, { "type": "construction_group", "id": "install_upgraded_solar_panel", diff --git a/data/json/furniture_and_terrain/furniture-appliances.json b/data/json/furniture_and_terrain/furniture-appliances.json index c8ec34ca2bbd..437dc70331b0 100644 --- a/data/json/furniture_and_terrain/furniture-appliances.json +++ b/data/json/furniture_and_terrain/furniture-appliances.json @@ -909,6 +909,87 @@ ] } }, + { + "type": "furniture", + "id": "f_battery_small", + "copy-from": "f_battery", + "name": "mounted small storage battery", + "description": "A small storage battery, connected to building's electric grid.", + "symbol": ":", + "color": "blue_white", + "move_cost_mod": 2, + "coverage": 10, + "active": [ "battery", { "max_stored": 500 } ], + "deconstruct": { + "items": [ + { "item": "sheet_metal_small", "count": [ 2, 4 ] }, + { "item": "cable", "charges": [ 2, 5 ] }, + { "item": "small_storage_battery", "count": 1 } + ] + }, + "bash": { + "str_min": 8, + "str_max": 20, + "sound": "metal screeching!", + "sound_fail": "clang!", + "items": [ + { "item": "scrap", "count": [ 2, 4 ] }, + { "item": "sheet_metal_small", "count": [ 0, 2 ] }, + { "item": "cable", "charges": [ 1, 3 ] } + ] + } + }, + { + "type": "furniture", + "id": "f_battery_car", + "copy-from": "f_battery_small", + "name": "mounted car battery", + "description": "A lead-acid battery salvaged from a vehicle and connected to building's electric grid.", + "symbol": ":", + "color": "blue_white", + "active": [ "battery", { "max_stored": 2500 } ], + "deconstruct": { + "items": [ + { "item": "sheet_metal_small", "count": [ 2, 4 ] }, + { "item": "cable", "charges": [ 2, 5 ] }, + { "item": "battery_car", "count": 1 } + ] + } + }, + { + "type": "furniture", + "id": "f_battery_motorbike", + "copy-from": "f_battery_small", + "name": "mounted motorbike battery", + "description": "A small lead-acid battery salvaged from a vehicle and connected to building's electric grid.", + "symbol": ":", + "color": "blue_white", + "active": [ "battery", { "max_stored": 500 } ], + "deconstruct": { + "items": [ + { "item": "sheet_metal_small", "count": [ 2, 4 ] }, + { "item": "cable", "charges": [ 2, 5 ] }, + { "item": "battery_motorbike", "count": 1 } + ] + } + }, + { + "type": "furniture", + "id": "f_battery_motorbike_small", + "copy-from": "f_battery_small", + "name": "mounted small motorbike battery", + "description": "A tiny lead-acid battery salvaged from a vehicle and connected to building's electric grid. Better than nothing if you're desperate to turn the lights back on.", + "symbol": ":", + "color": "blue_white", + "active": [ "battery", { "max_stored": 150 } ], + "deconstruct": { + "items": [ + { "item": "sheet_metal_small", "count": [ 2, 4 ] }, + { "item": "cable", "charges": [ 2, 5 ] }, + { "item": "battery_motorbike_small", "count": 1 } + ] + } + }, { "type": "furniture", "id": "f_charger", From 1efef0f3024c985548bf96b20056cc218b37c3b1 Mon Sep 17 00:00:00 2001 From: Chaosvolt Date: Tue, 26 Sep 2023 03:28:08 -0500 Subject: [PATCH 23/28] Add street lights to more places, allow deconstructing (#3265) * Add street lights to more places, allow deconstructing * Update furniture-terrains.json * Update megastore.json * Update homeimprovement_superstore_new.json --- .../furniture-terrains.json | 12 +++- .../json/mapgen/abandoned_shopping_plaza.json | 8 ++- data/json/mapgen/abstorefront.json | 10 ++-- data/json/mapgen/bank.json | 9 ++- data/json/mapgen/bus_station.json | 4 +- data/json/mapgen/cs_public_space.json | 5 +- .../mapgen/homeimprovement_superstore.json | 8 ++- .../homeimprovement_superstore_new.json | 4 +- data/json/mapgen/hospital.json | 18 +++--- data/json/mapgen/mall/mall_ground.json | 60 +++++++++---------- data/json/mapgen/megastore.json | 4 +- data/json/mapgen/motel.json | 32 ++++++---- data/json/mapgen/stadium_football.json | 36 ++++++++--- data/json/mapgen/town_hall.json | 6 +- data/json/mapgen/zoo.json | 12 ++-- data/json/mapgen_palettes/hospital.json | 3 + data/json/mapgen_palettes/mall_palette.json | 2 + .../homeimprovement_superstore_new.json | 2 + 18 files changed, 154 insertions(+), 81 deletions(-) diff --git a/data/json/furniture_and_terrain/furniture-terrains.json b/data/json/furniture_and_terrain/furniture-terrains.json index e6baf079c8a3..043289a5a766 100644 --- a/data/json/furniture_and_terrain/furniture-terrains.json +++ b/data/json/furniture_and_terrain/furniture-terrains.json @@ -723,6 +723,16 @@ "coverage": 40, "required_str": 32, "flags": [ "BASHABLE" ], + "deconstruct": { + "items": [ + { "item": "pipe", "count": 8 }, + { "item": "sheet_metal", "count": 2 }, + { "item": "amplifier", "count": 4 }, + { "item": "light_bulb", "count": 2 }, + { "item": "cable", "charges": 4 }, + { "item": "plastic_chunk", "count": 4 } + ] + }, "bash": { "str_min": 30, "str_max": 100, @@ -732,7 +742,7 @@ { "item": "pipe", "count": [ 1, 7 ] }, { "item": "scrap", "count": [ 3, 12 ] }, { "item": "amplifier", "count": [ 1, 3 ] }, - { "item": "light_bulb", "count": [ 0, 3 ] }, + { "item": "light_bulb", "count": [ 0, 2 ] }, { "item": "cable", "charges": [ 1, 2 ] }, { "item": "plastic_chunk", "count": [ 2, 4 ] } ] diff --git a/data/json/mapgen/abandoned_shopping_plaza.json b/data/json/mapgen/abandoned_shopping_plaza.json index 194ac89737a3..52241dfd5e27 100644 --- a/data/json/mapgen/abandoned_shopping_plaza.json +++ b/data/json/mapgen/abandoned_shopping_plaza.json @@ -4,6 +4,7 @@ "id": "shoppingplaza", "terrain": { " ": "t_floor", + "'": "t_sidewalk", "+": "t_door_locked", ",": [ "t_grass", "t_grass", "t_grass", "t_dirt" ], "-": "t_wall_h", @@ -30,6 +31,7 @@ "|": "t_wall_v" }, "furniture": { + "'": "f_street_light", "A": "f_rack", "B": "f_toilet", "C": "f_counter", @@ -70,7 +72,7 @@ "7...y...y...y...y...y...y...y...y...y...y...y...y...y...y...y...y...y...", "7yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", "455555555555555555555555555555555555555555555555555555555555555555555555", - "455555555555555555555555555555555555555555555555555555555555555555555555", + "455555555555555555555555'55555555555555555555555'55555555555555555555555", "|-111111---++---111111-||-111111--5555--111111-||-111111---++---111111-|", "| 1 1 || |-++-| || 1 1 |", "| 1 1 || || 1 1 |", @@ -131,12 +133,12 @@ "..........................................yyyyyy551 |", "y...y...y...y...y...y...y...y...y..............y551 |", "y...y...y...y...y...y...y...y...y..............y551 |", - "y...y...y...y...y...y...y...y...y..........55555551 |", + "y...y...y...y...y...y...y...y...y..........'5555551 |", "y...y...y...y...y...y...y...y...y..........55555551 |", "y...y...y...y...y...y...y...y...y..............y55| |", "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy55|---------------------", "55555555555555555555555555555555555555555555555555+ A|", - "55555555555555555555555555555555555555555555555555+ A A A A A|", + "'55555555555555555555555'5555555555555555555555555+ A A A A A|", "|-111111---++---111111-||-111111--5555--111111-|--| A A A A A|", "| 1 1 || |-++-| |A A A A A A|", "| 1 1 || |A FHF A A A A A|", diff --git a/data/json/mapgen/abstorefront.json b/data/json/mapgen/abstorefront.json index f867b7cd1441..f7c7429509fe 100644 --- a/data/json/mapgen/abstorefront.json +++ b/data/json/mapgen/abstorefront.json @@ -6,7 +6,7 @@ "object": { "fill_ter": "t_floor", "rows": [ - " ", + " '", " |-xxxxxxxxDDxxxxxxxx-| ", " |...................B| ", " |B..c........B..B...B| ", @@ -54,6 +54,7 @@ "t_dirt" ], " ": "t_sidewalk", + "'": "t_sidewalk", "+": "t_door_c", "-": "t_wall_w", ".": "t_floor", @@ -63,7 +64,7 @@ "<": "t_stairs_up", "|": "t_wall_w" }, - "furniture": { "B": "f_rack", "c": "f_counter" }, + "furniture": { "B": "f_rack", "c": "f_counter", "'": "f_street_light" }, "items": { ".": { "item": "trash", "chance": 12 } }, "vehicles": { ".": { "vehicle": "shopping_cart", "chance": 1, "status": 1 } } } @@ -135,7 +136,7 @@ "fill_ter": "t_floor", "rows": [ "_______ ", - "_______ ", + "_______' ", "___~~~~O |-xx--xx-| ", "_______O b|B......B| ", "_______O b|B..BB..B| ", @@ -182,6 +183,7 @@ "t_dirt" ], " ": "t_sidewalk", + "'": "t_sidewalk", "_": "t_pavement", "~": "t_pavement_y", "+": "t_door_c", @@ -196,7 +198,7 @@ "<": "t_ladder_up", "|": "t_wall_w" }, - "furniture": { "B": "f_rack", "R": "f_dumpster", "l": "f_locker", "b": "f_bench", "c": "f_counter" }, + "furniture": { "B": "f_rack", "R": "f_dumpster", "l": "f_locker", "b": "f_bench", "c": "f_counter", "'": "f_street_light" }, "items": { ".": { "item": "trash", "chance": 15 } }, "vehicles": { ".": { "vehicle": "shopping_cart", "chance": 1, "status": 1 } } } diff --git a/data/json/mapgen/bank.json b/data/json/mapgen/bank.json index b3a08c3fc6f1..128f3b1ca8d8 100644 --- a/data/json/mapgen/bank.json +++ b/data/json/mapgen/bank.json @@ -7,7 +7,7 @@ "object": { "fill_ter": "t_floor", "rows": [ - " S SIS ", + " S'S S SIS ", " #gggggggGgggggggggggg# ", " #A..........CTC.CTC.p# ", " #A...................w ", @@ -34,6 +34,7 @@ ], "terrain": { " ": [ "t_grass", "t_grass", "t_grass", "t_dirt", "t_shrub" ], + "'": "t_sidewalk", "#": "t_wall_w", "$": "t_metal_floor", "%": [ "t_door_c", "t_door_c", "t_door_locked_interior" ], @@ -54,7 +55,7 @@ "w": "t_window_alarm" }, "furniture": { - "$": "f_safe_l", + "'": "f_street_light", "C": "f_chair", "T": "f_table", "c": "f_counter", @@ -144,7 +145,7 @@ "object": { "fill_ter": "t_floor", "rows": [ - " SS SSS", + " SS S'S SSS", " ggGGgggggggggg#######iS", " gA.........ccx.#....##S", " gA........C-C..+....p# ", @@ -171,6 +172,7 @@ ], "terrain": { " ": [ "t_grass", "t_grass", "t_grass", "t_dirt" ], + "'": "t_sidewalk", "_": "t_metal_floor", "|": [ "t_door_c", "t_wall_w", "t_wall_w", "t_wall_w", "t_wall_w", "t_wall_w", "t_wall_w", "t_wall_w", "t_wall_w" ], "I": "t_wall_w", @@ -197,6 +199,7 @@ "w": "t_window_alarm" }, "furniture": { + "'": "f_street_light", "a": "f_armchair", "D": "f_sofa", "o": "f_bookcase", diff --git a/data/json/mapgen/bus_station.json b/data/json/mapgen/bus_station.json index 50d86028f638..4e9b49f793b1 100644 --- a/data/json/mapgen/bus_station.json +++ b/data/json/mapgen/bus_station.json @@ -7,7 +7,7 @@ "object": { "fill_ter": "t_floor", "rows": [ - "...........ss________sssssssssssssssPyyyyy___sss", + "...........!s________sssssssssssssssPyyyyy___s!s", "....,,,....ss________s,;,,,;,,;,,,;,syyyyy___s,s", "||||www||||ss________ssssssssssssssss________s;s", "|p p|ss________________________________s,s", @@ -34,6 +34,7 @@ ], "terrain": { " ": "t_floor", + "!": "t_concrete", "+": "t_door_c", ".": [ [ "t_dirt", 5 ], [ "t_grass", 16 ], [ "t_grass_long", 5 ] ], ",": [ @@ -70,6 +71,7 @@ "f": "t_chainfence" }, "furniture": { + "!": "f_street_light", "c": "f_counter", "S": "f_sink", "B": "f_bench", diff --git a/data/json/mapgen/cs_public_space.json b/data/json/mapgen/cs_public_space.json index a4109b8b7bcd..dfbd3edb3e8e 100644 --- a/data/json/mapgen/cs_public_space.json +++ b/data/json/mapgen/cs_public_space.json @@ -7,7 +7,7 @@ "object": { "rows": [ "...,....'''''''',...,,..", - "..,...,.'I''''I',..,...,", + "..,...,!'I''''I'!..,...,", "..,...,.''''''''.....,..", "...,fsfsfs,'',sfsfsf,.,.", ".,.f,,,,,,,'',,,,,,,f...", @@ -34,6 +34,7 @@ "terrain": { ".": "t_grass", ",": "t_dirt", + "!": "t_sidewalk", "'": "t_sidewalk", "w": "t_water_sh", "s": "t_underbrush", @@ -44,7 +45,7 @@ "N": "t_sidewalk", "f": "t_dirtmound" }, - "furniture": { "S": "f_statue", "b": "f_bench", "D": "f_dumpster", "N": "f_bulletin", "f": "f_bluebell" }, + "furniture": { "!": "f_street_light", "S": "f_statue", "b": "f_bench", "D": "f_dumpster", "N": "f_bulletin", "f": "f_bluebell" }, "items": { "D": { "item": "oa_custom_trash", "chance": 70 }, "b": { "item": "oa_discarded_news", "chance": 5 } }, "place_loot": [ { "item": "american_flag", "x": 10, "y": 1, "chance": 25 } ] } diff --git a/data/json/mapgen/homeimprovement_superstore.json b/data/json/mapgen/homeimprovement_superstore.json index 8db8b3f69ab1..29324da56e6e 100644 --- a/data/json/mapgen/homeimprovement_superstore.json +++ b/data/json/mapgen/homeimprovement_superstore.json @@ -44,10 +44,11 @@ "________________________", "________________________", "..........|_____________", - "..........|_____________", + "..........|!____________", "-----------_____________" ], "terrain": { + "!": "t_pavement", "$": "t_floor", "&": "t_floor", "+": "t_door_glass_c", @@ -66,6 +67,7 @@ "|": "t_wall" }, "furniture": { + "!": "f_street_light", "$": "f_vending_c", "C": "f_chair", "T": "f_table", @@ -113,11 +115,12 @@ "________________________", "________________________", "___________|............", - "___________|............", + "__________!|............", "___________-------------" ], "terrain": { "$": "t_floor", + "!": "t_pavement", "&": "t_floor", "+": "t_door_glass_c", ",": "t_pavement_y", @@ -138,6 +141,7 @@ "|": "t_wall" }, "furniture": { + "!": "f_street_light", "$": "f_vending_c", "&": "f_trashcan", "C": "f_chair", diff --git a/data/json/mapgen/homeimprovement_superstore_new.json b/data/json/mapgen/homeimprovement_superstore_new.json index 9d43fc0088a3..0f39624c9432 100644 --- a/data/json/mapgen/homeimprovement_superstore_new.json +++ b/data/json/mapgen/homeimprovement_superstore_new.json @@ -84,7 +84,7 @@ "&S_______SS____,____,____,____,____,____,____SBS", " S_______SS____,____,____,____,____,____,____S S", " S_______SS__________________________________S/S", - "&S_______SS__________________________________SSS", + "&S_______[S__________________________________S[S", "/S_______SS__________________________________SSS", "************************************************", "*zzzzz***********??????????????????????????????*", @@ -270,6 +270,7 @@ "|": "t_wall", "O": "t_flat_roof", "S": "t_sidewalk", + "[": "t_sidewalk", "?": "t_railing", "*": "t_open_air", "z": "t_flat_roof", @@ -278,6 +279,7 @@ "Z": "t_glass_roof" }, "furniture": { + "[": "f_street_light", "V": "f_vending_c", "C": "f_chair", "T": "f_table", diff --git a/data/json/mapgen/hospital.json b/data/json/mapgen/hospital.json index f706ed72ff28..d074b3465a09 100644 --- a/data/json/mapgen/hospital.json +++ b/data/json/mapgen/hospital.json @@ -11,15 +11,15 @@ "object": { "fill_ter": "t_dirt", "rows": [ - "_______________________________________________________########;########", - "_______________________________________________________#...cT#...#Tc...#", - "_:____:____:____:_________:____:____:____:____:____:___#BB...+...+...BB#", - "_:____:____:____:_________:____:____:____:____:____:___#BB...+...+...BB#", - "_:____:____:____:_________:____:____:____:____:____:___#....l#...#l....#", - "_:____:____:____:_________:____:____:____:____:____:___#######...#######", - "_:____:____:____:_________:____:____:____:____:____:___#....l#...#l....#", - "_:____:____:____:_________:____:____:____:____:____:___#BB...+...+...BB#", - "_______________________________________________________#BB...+...+...BB#", + "______________________________________________________,########;########", + "______________________________________________________'#...cT#...#Tc...#", + "_:____:____:____:_________:____:____:____:____:____:__,#BB...+...+...BB#", + "_:____:____:____:_________:____:____:____:____:____:__,#BB...+...+...BB#", + "_:____:____:____:_________:____:____:____:____:____:__,#....l#...#l....#", + "_:____:____:____:_________:____:____:____:____:____:__,#######...#######", + "_:____:____:____:_________:____:____:____:____:____:__,#....l#...#l....#", + "_:____:____:____:_________:____:____:____:____:____:__,#BB...+...+...BB#", + ",',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#BB...+...+...BB#", "####################//####xxxxxxxxxxxxxxxxxxxxxxxxxx#;;#...cT#...#Tc...#", "#&#&#&#&#&#sssss#.........TbbbbTbbbbTbbbbTbbbbTbbbbT#``#######...#######", "#.#.#.#.#.#.....#..................................b#``#...cT#...#Tc...#", diff --git a/data/json/mapgen/mall/mall_ground.json b/data/json/mapgen/mall/mall_ground.json index 211718090dcc..46790154b544 100644 --- a/data/json/mapgen/mall/mall_ground.json +++ b/data/json/mapgen/mall/mall_ground.json @@ -239,7 +239,7 @@ "__,,___,________________", "_,,_____________________", "_,,_____________________", - "_,,_____ssssssssss______", + "_,,_____sssssssss'______", "_,,____sss______________", "_,,____ss_______________", "_,,____ss_______________", @@ -280,7 +280,7 @@ "________________________", "________________________", "________________________", - "____sssssssssssssssssss_", + "____'sssssssssssssssss'_", "___________ssss_________", "____________ss__________", "____________ss__________", @@ -323,7 +323,7 @@ "________________________", "________________________", "________________________", - "_________sssssssssssssss", + "_________'ssssssssssssss", "________________ssss____", "_________________ss_____", "_________________ss_____", @@ -366,7 +366,7 @@ "______________s.....#T#.", "______________s.....###.", "______________ss........", - "ssss___________ssssssss.", + "sss'___________ssssssss.", "_____________________ss.", "______________________s.", "______________________s.", @@ -639,7 +639,7 @@ "_______ss____________,,,", "_______ss_____________,,", "_______sss______________", - "________ssssssssss______", + "________sssssssss'______", "_________sssssssss__,,,,", "________________________", "________________________", @@ -681,7 +681,7 @@ ",___________ss__________", "____________ss__________", "___________ssss_________", - "____sssssssssssssssssss_", + "____'sssssssssssssssss'_", ",,__sssssssssssssssssss_", "________________________", "________________________", @@ -725,7 +725,7 @@ "__,,,,___________ss_____", "___,,____________ss_____", "________________ssss____", - "_________sssssssssssssss", + "_________'ssssssssssssss", "_,,,,,,__sssssssssssssss", "________________________", "________________________", @@ -769,7 +769,7 @@ "_______,,,,___________s.", "________,,____________s.", "_____________________ss.", - "ssss___________sssssss..", + "sss'___________sssssss..", "ssss__,,,,,,__ss........", "______________s..#####..", "______________s.##...##.", @@ -1165,7 +1165,7 @@ "..####...###.....sss..T.", "----------|#..###.sss...", " r|#..#T#.ssssss", - " c r|...###ssss___", + " c r|...###sss'___", " c6ccc6c|-|-|sssssss____", " [ [sspssss____", " [ [sssssss____", @@ -1317,7 +1317,7 @@ ".aAAssAAAasssUUss|e cc", "....ss...asssssss|r rc ", "ssssss...|-|HHH|-|--+--|", - "___sss..#| |ccc: |t S|", + "___'ss..#| |ccc: |t S|", "____ss.##| |---| |-----|", "____ss..#| ", "____ss...| |--:--|---", @@ -2249,7 +2249,7 @@ "____ss...Vc| | + rr ", "____ss...Vc| |-| rr rr ", "____ss...|:| | rr ", - "___sss.|-| | | ", + "___'ss.|-| | | ", "ssssss.|< -::-|--|cccc|", "...sss.|-|2222yV22|HHHH|", "###.sssssZ21112Z22222222", @@ -2260,7 +2260,7 @@ "###.sssssZ21112Z21111111", "...sss.|-|2222yV22222222", "ssssss.|< -::-|HHH|-HHH", - "___sss.|-| | :ccc|r hn", + "___'ss.|-| | :ccc|r hn", "____ss...|:| |---|r ", "____ss...Vc| |rrrrr r", "____ss...Vc| ||r ", @@ -2581,7 +2581,7 @@ " c|##.....ss____", " h c|##.....ss____", " S|##.###.ss____", - "nhhn P|-|.#T#.sss___", + "nhhn P|-|.#T#.ss'___", "-HHH-HHH|-|.|.###sssssss", "22222222|y|||..psss.....", "11111112Z22Zssssss.#####", @@ -2592,7 +2592,7 @@ "11111112Z22Zssssss.#####", "22222222|y|||..psss.....", "-HHH-HHH|-|.|.###sssssss", - " B|-|.#T#.sss___", + " B|-|.#T#.ss'___", "BBBBBBB B|...###.ss____", "BBBBBBB B|.......ss____", " B|.......ss____", @@ -3251,11 +3251,11 @@ "____ss.##|---------|----", "____ss..###..###....###.", "____ss...#....#......#..", - "___ssss.................", + "___'sss.................", "ssssssssssssssssssssssss", "..ssssssssssssssssssssss", - "..ssssssssssssssssssssss", - ".ss_____,______,______,_", + ".sssssssssssssssssssssss", + ".s'_____,______,______,_", ".s______,______,______,_", ".s______,______,______,_", "#s______,______,______,_" @@ -3315,8 +3315,8 @@ "........................", "ssssssssssssssssssssssss", "ssssssssssssssssssssssss", - "ssssssssssss.....sssssss", - "_____,_____ss...ss_____,", + "sssssssssssss...ssssssss", + "_____,_____'s...s'_____,", "_____,______s.#.s______,", "_____,______s###s______,", "_____,______s#T#s______," @@ -3377,8 +3377,8 @@ "....................|---", "ssssssssssssssssssssssss", "ssssssssssssssssssssssss", - "ssssssssssssssssssss....", - "______,______,_____ss.#.", + "sssssssssssssssssssss...", + "______,______,_____'s.#.", "______,______,______s.#.", "______,______,______s.#.", "______,______,______s.#." @@ -3433,8 +3433,8 @@ "|sspsssssssssssssssspss|", "ssssssssssssssssssssssss", "ssssssspsspsspsspsssssss", - ".sssssssssssssssssssss..", - "ss____________________ss", + "ssssssssssssssssssssssss", + "s'____________________'s", "s______________________s", "s______________________s", "s______________________s" @@ -3473,8 +3473,8 @@ "---|....................", "ssssssssssssssssssssssss", "ssssssssssssssssssssssss", - "....ssssssssssssssssssss", - ".#.ss_____,______,______", + "...sssssssssssssssssssss", + ".#.s'_____,______,______", ".#.s______,______,______", ".#.s______,______,______", ".#.s______,______,______" @@ -3533,8 +3533,8 @@ "........................", "ssssssssssssssssssssssss", "ssssssssssssssssssssssss", - "sssssss.....ssssssssssss", - ",_____ss...ss_____,_____", + "ssssssss...sssssssssssss", + ",_____'s...s'_____,_____", ",______s.#.s______,_____", ",______s###s______,_____", ",______s#T#s______,_____" @@ -3589,11 +3589,11 @@ "HHHH-HHHH-|...###.ss____", "#..###........#T#.ss____", "....#.........###.ss____", - ".................ssss___", + ".................sss'___", "ssssssssssssssssssssssss", "ssssssssssssssssssssss..", - "ssssssssssssssssssssss..", - "_,______,______,_____ss.", + "sssssssssssssssssssssss.", + "_,______,______,_____'s.", "_,______,______,______s.", "_,______,______,______s.", "_,______,______,______s#" diff --git a/data/json/mapgen/megastore.json b/data/json/mapgen/megastore.json index d147f8e6fe7c..599a428b0378 100644 --- a/data/json/mapgen/megastore.json +++ b/data/json/mapgen/megastore.json @@ -177,7 +177,7 @@ "object": { "fill_ter": "t_pavement", "rows": [ - "#W....................WT", + "'W....................WT", "W......................W", "........................", "______............______", @@ -204,12 +204,14 @@ ], "rotation": 0, "terrain": { + "'": "t_dirt", ".": "t_pavement", "_": "t_pavement_y", "#": [ "t_underbrush", "t_grass" ], "T": [ "t_tree_young", "t_tree" ], "W": "t_sidewalk" }, + "furniture": { "'": "f_street_light" }, "vehicles": { "v": { "vehicle": "city_vehicles", "chance": 10 } } } }, diff --git a/data/json/mapgen/motel.json b/data/json/mapgen/motel.json index 109cf2c500d1..8b474fc248c9 100644 --- a/data/json/mapgen/motel.json +++ b/data/json/mapgen/motel.json @@ -35,7 +35,7 @@ "-MM-gg------#._________#", ".SS##########._________#", ".SS..........._________#", - "SSSSSSSSSSSSSS_________#", + "SSSSSSSSSSSS!S_________#", "SSSSSSSSSSSSSS_________#", "_______________________#", "_______________________#", @@ -49,6 +49,7 @@ "set": [ { "point": "terrain", "id": "t_dirt", "x": 23, "y": [ 0, 23 ], "repeat": [ 5, 10 ] } ], "terrain": { " ": "t_floor", + "!": "t_sidewalk", "#": "t_shrub", "'": "t_pavement_y", "+": "t_door_c", @@ -86,6 +87,7 @@ "~": "t_fence_h" }, "furniture": { + "!": "f_street_light", "6": "f_table", "7": "f_bookcase", "8": "f_bathtub", @@ -388,7 +390,7 @@ "_______________________#", "_______________________#", "_______________________#", - "SSSSSSSSSSSSSSSSSSSSSSS#", + "SSSSSSSSSSSSSSSSSSSSS!S#", "SSSSSSSSSSSSSSSSSSSSSSS#", "-22+---22+---223--223---", " C| C| C| C|", @@ -406,6 +408,7 @@ "set": [ { "point": "terrain", "id": "t_dirt", "x": [ 0, 23 ], "y": 23, "repeat": [ 5, 10 ] } ], "terrain": { " ": "t_floor", + "!": "t_sidewalk", "#": "t_shrub", "'": "t_pavement_y", "+": "t_door_c", @@ -445,6 +448,7 @@ "~": "t_fence_h" }, "furniture": { + "!": "f_street_light", "6": "f_table", "7": "f_bookcase", "8": "f_bathtub", @@ -731,7 +735,7 @@ "-MM-gg------#._________#", ".SS##########._________#", ".SS..........._________#", - "SSSSSSSSSSSSSS_________#", + "SSSSSSSSSSSS!S_________#", "SSSSSSSSSSSSSS_________#", "_______________________#", "_______________________#", @@ -744,6 +748,7 @@ ], "terrain": { ".": "t_grass", + "!": "t_sidewalk", "-": "t_wall", "_": "t_pavement", "'": "t_pavement_y", @@ -781,6 +786,7 @@ "x": "t_fencegate_c" }, "furniture": { + "!": "f_street_light", "6": "f_table", "7": "f_bookcase", "8": "f_bathtub", @@ -1070,11 +1076,11 @@ "_______________________#", "_______________________#", "_______________________#", - "_______________________#", - "_______________________#", - "_______________________#", - "SSSSSSSSSSSSSSSSSSSSSSS#", - "SSSSSSSSSSSSSSSSSSSSSS<#", + "______________________SS", + "______________________!S", + "______________________SS", + "SSSSSSSSSSSSSSSSSSSSSSSS", + "SSSSSSSSSSSSSSSSSSSSSSt|_))))))),,,,,,,))))))))))))),,,,,,,_wtbbt|", "|.c>.+_),C,a,,,,,,,,,,``,,,),,,,,,,,,,,,,_+....|", @@ -1600,6 +1608,7 @@ ], "terrain": { "*": [ "t_grass", "t_grass", "t_grass", "t_grass", "t_dirt" ], + "!": "t_sidewalk", ".": "t_floor", "%": "t_floor", "&": "t_floor", @@ -1634,6 +1643,7 @@ "Q": "t_pavement" }, "furniture": { + "!": "f_street_light", "d": "f_dumpster", "b": "f_bed", "c": "f_chair", @@ -1680,7 +1690,7 @@ "object": { "rows": [ "______________,,,,,,,_____________,,,,,,,_______", - "______________,,,,,,,_____________,,,,,,,_______", + "____________!_,,,,,,,_____________,,,,,,,_!_____", "|----|________,,,,,,,_____________,,,,,,,_|----|", "|T.>t|_))))))),,,,,,,))))))))))))),,,,,,,_wtbbt|", "|.c>.+_),,,,,,,,,,,,,,,,,,,),,,,,,,,,,,,,_+....|", @@ -1706,6 +1716,7 @@ ], "terrain": { "*": [ "t_grass", "t_grass", "t_grass", "t_grass", "t_dirt" ], + "!": "t_sidewalk", ".": "t_floor", "%": "t_floor", "&": "t_floor", @@ -1730,6 +1741,7 @@ ")": "t_pavement_y" }, "furniture": { + "!": "f_street_light", "b": "f_bed", "c": "f_chair", "t": "f_table", diff --git a/data/json/mapgen/stadium_football.json b/data/json/mapgen/stadium_football.json index ac24e27fe677..972d0df435a0 100644 --- a/data/json/mapgen/stadium_football.json +++ b/data/json/mapgen/stadium_football.json @@ -39,6 +39,7 @@ "method": "json", "object": { "furniture": { + "!": "f_street_light", "#": "f_bench", "&": "f_sink", "+": "f_null", @@ -79,7 +80,7 @@ ], "place_monster": [ { "group": "GROUP_ZOMBIE", "x": [ 4, 20 ], "y": [ 4, 20 ], "repeat": [ 4, 10 ] } ], "rows": [ - "ssssssssssssssssssssssss", + "!sssssssssssssssssssssss", "__________----__________", "_________------_________", "_-----------------------", @@ -105,6 +106,7 @@ "-.....|...|#c#c#crcgg___" ], "terrain": { + "!": "t_sidewalk", "#": "t_concrete", "&": "t_thconc_floor", "+": "t_door_metal_c", @@ -430,7 +432,7 @@ { "method": "json", "object": { - "furniture": { "#": "f_bench", "&": "f_trashcan", ".": "f_null", "_": "f_null", "g": "f_null", "p": "f_null" }, + "furniture": { "!": "f_street_light", "#": "f_bench", "&": "f_trashcan", ".": "f_null", "_": "f_null", "g": "f_null", "p": "f_null" }, "place_items": [ { "chance": 65, "item": "trash", "x": 17, "y": 20 } ], "rows": [ "gggg.....gggg.....gggggg", @@ -449,7 +451,7 @@ ".....p.....p............", ".....p.....p............", ".....p.....p............", - "................________", + "................!_______", "................________", "................_#______", "................_#______", @@ -458,7 +460,15 @@ ".....p....p.....________", "._______________________" ], - "terrain": { "#": "t_sidewalk", "&": "t_sidewalk", ".": "t_pavement", "_": "t_sidewalk", "g": "t_grass", "p": "t_pavement_y" } + "terrain": { + "!": "t_sidewalk", + "#": "t_sidewalk", + "&": "t_sidewalk", + ".": "t_pavement", + "_": "t_sidewalk", + "g": "t_grass", + "p": "t_pavement_y" + } }, "om_terrain": "stadium_1_0", "type": "mapgen", @@ -709,7 +719,7 @@ { "method": "json", "object": { - "furniture": { "#": "f_bench", "&": "f_trashcan", ".": "f_null", "_": "f_null", "g": "f_null", "p": "f_null" }, + "furniture": { "!": "f_street_light", "#": "f_bench", "&": "f_trashcan", ".": "f_null", "_": "f_null", "g": "f_null", "p": "f_null" }, "place_items": [ { "chance": 65, "item": "trash", "x": 6, "y": 20 } ], "rows": [ "gggg.....gggg.....gggggg", @@ -728,7 +738,7 @@ "...............p....p...", "........................", "........................", - "________................", + "_______!................", "________................", "______#_................", "______#_................", @@ -737,7 +747,15 @@ "________....p....p......", "________________________" ], - "terrain": { "#": "t_sidewalk", "&": "t_sidewalk", ".": "t_pavement", "_": "t_sidewalk", "g": "t_grass", "p": "t_pavement_y" } + "terrain": { + "!": "t_sidewalk", + "#": "t_sidewalk", + "&": "t_sidewalk", + ".": "t_pavement", + "_": "t_sidewalk", + "g": "t_grass", + "p": "t_pavement_y" + } }, "om_terrain": "stadium_2_0", "type": "mapgen", @@ -1003,6 +1021,7 @@ "method": "json", "object": { "furniture": { + "!": "f_street_light", "#": "f_bench", "&": "f_toilet", "+": "f_null", @@ -1052,7 +1071,7 @@ ], "place_vehicles": [ { "chance": 3, "fuel": 3, "rotation": 270, "status": -1, "vehicle": "ice_cream_cart", "x": 10, "y": 11 } ], "rows": [ - "ssssssssssssssssssssssss", + "sssssssssssssssssssssss!", "__________----__________", "_________------_________", "------------------------", @@ -1078,6 +1097,7 @@ "___ggcrc#c#c#|...|.....-" ], "terrain": { + "!": "t_sidewalk", "#": "t_concrete", "&": "t_thconc_floor", "+": "t_door_glass_c", diff --git a/data/json/mapgen/town_hall.json b/data/json/mapgen/town_hall.json index 2bcbdca22308..3af289157d2f 100644 --- a/data/json/mapgen/town_hall.json +++ b/data/json/mapgen/town_hall.json @@ -26,6 +26,7 @@ "O": "t_linoleum_white", "u": "t_linoleum_white", "s": "t_sidewalk", + "[": "t_sidewalk", "x": "t_console_broken", "|": "t_brick_wall", "!": "t_door_glass_c", @@ -34,6 +35,7 @@ "v": "t_window" }, "furniture": { + "[": "f_street_light", "3": "f_bench", "B": "f_bench", "S": "f_sink", @@ -91,7 +93,7 @@ "fill_ter": "t_floor", "rows": [ "ssssssssssssssssssssssssssssssssssssssssssssssss", - ".ssssssssssssssssssssssssssssssssssssssssssssss.", + "[ssssssssssssssssssssssssssssssssssssssssssssss[", ".s.....||vvvv||......ssssss......||vvvv||.....s.", ".s.|||||p p|||||...ssss...|||||pBBBBp|||||.s.", ".s.|T+i|c c|i+T|...3ss3...|p p|.s.", @@ -134,7 +136,7 @@ ".s.||||| #### |||||''||||||||| c xc|||||.s.", ".s..,,,| cc + hx|''+'''|x h hc hc hd|,,,..s.", ".s..,,,|h h|ddx|''|lll|ddc ddx ddx d|,,,..s.", - ".ss..,,|||vv|||||||--|||||||||||||||vv|||,,..ss.", + ".ss[.,,|||vv|||||||--|||||||||||||||vv|||,,.[ss.", "..ss...............ss.......................ss..", "...ssssssssssssssssssssssssssssssssssssssssss...", "................................................", diff --git a/data/json/mapgen/zoo.json b/data/json/mapgen/zoo.json index acad92cfd315..fa4a6d193767 100644 --- a/data/json/mapgen/zoo.json +++ b/data/json/mapgen/zoo.json @@ -44,12 +44,13 @@ "_....p....p....p....p...", "_....p....p....p....p...", "_....p....p....p....p...", - "_sssssssssssssssssssssss", + "_'ssssssssssssssssssssss", "____d____________d____ss", "___d7d__________d4d___ss", "____d____________d____ss" ], "terrain": { + "'": "t_sidewalk", ".": "t_pavement", "4": "t_tree_pine", "7": "t_tree_apple_harvested", @@ -57,7 +58,8 @@ "d": "t_dirt", "p": "t_pavement_y", "s": "t_sidewalk" - } + }, + "furniture": { "'": "f_street_light" } } }, { @@ -417,12 +419,13 @@ ".....p....p....p....p___", ".....p....p....p....p___", ".....p....p....p....p___", - "sssssssssssssssssssss___", + "ssssssssssssssssssss'___", "ss__d____________d______", "ss_d7d__________d4d_____", "ss__d____________d______" ], "terrain": { + "'": "t_sidewalk", ".": "t_pavement", "4": "t_tree_pine", "7": "t_tree_apple_harvested", @@ -430,7 +433,8 @@ "d": "t_dirt", "p": "t_pavement_y", "s": "t_sidewalk" - } + }, + "furniture": { "'": "f_street_light" } } }, { diff --git a/data/json/mapgen_palettes/hospital.json b/data/json/mapgen_palettes/hospital.json index 2d28835bf146..f32bd0bf51d8 100644 --- a/data/json/mapgen_palettes/hospital.json +++ b/data/json/mapgen_palettes/hospital.json @@ -4,6 +4,8 @@ "id": "hospital", "terrain": { " ": "t_region_groundcover_urban", + ",": "t_sidewalk", + "'": "t_sidewalk", "#": "t_wall", ":": "t_pavement_y", "&": "t_floor", @@ -46,6 +48,7 @@ "?": "t_floor" }, "furniture": { + "'": "f_street_light", "*": "f_centrifuge", "b": "f_bench", "c": "f_chair", diff --git a/data/json/mapgen_palettes/mall_palette.json b/data/json/mapgen_palettes/mall_palette.json index 8138876cfd99..245d489b6519 100644 --- a/data/json/mapgen_palettes/mall_palette.json +++ b/data/json/mapgen_palettes/mall_palette.json @@ -5,6 +5,7 @@ "furniture": { "?": "f_sofa", "!": "f_rack", + "'": "f_street_light", "@": "f_bed", "$": "f_counter", "%": "f_indoor_plant", @@ -61,6 +62,7 @@ "terrain": { "#": "t_shrub", "!": "t_linoleum_gray_no_roof", + "'": "t_sidewalk", "$": "t_linoleum_white_no_roof", "%": "t_carpet_green", "^": "t_linoleum_white_no_roof", diff --git a/data/mods/No_Hope/Mapgen/homeimprovement_superstore_new.json b/data/mods/No_Hope/Mapgen/homeimprovement_superstore_new.json index 7a1b8fe1c01a..9d2af9abd840 100644 --- a/data/mods/No_Hope/Mapgen/homeimprovement_superstore_new.json +++ b/data/mods/No_Hope/Mapgen/homeimprovement_superstore_new.json @@ -269,6 +269,7 @@ "|": "t_wall", "O": "t_flat_roof", "S": "t_sidewalk", + "[": "t_sidewalk", "?": "t_railing", "*": "t_open_air", "z": "t_flat_roof", @@ -278,6 +279,7 @@ "x": "t_console_broken" }, "furniture": { + "[": "f_street_light", "V": "f_vending_c", "C": "f_chair", "T": "f_table", From 639a0e975d6620ab4037c5541a0ed9151daba46f Mon Sep 17 00:00:00 2001 From: scarf Date: Tue, 26 Sep 2023 17:28:12 +0900 Subject: [PATCH 24/28] feat: animal ears are cute (#3230) * feat: made animal tails not ugly ...except weaponized ones * feat: made animal ears pretty --- data/json/mutations/mutations.json | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 333a471d30e5..19412cb479aa 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -3020,7 +3020,6 @@ "name": { "str": "Stubby Tail" }, "points": 0, "visibility": 1, - "ugliness": 2, "description": "You have a short, stubby tail, like a rabbit's. It serves no purpose.", "types": [ "TAIL" ], "changes_to": [ "TAIL_LONG", "TAIL_THICK", "TAIL_FIN", "TAIL_RAT", "TAIL_RAPTOR" ], @@ -3032,7 +3031,6 @@ "name": { "str": "Tail Fin" }, "points": -2, "visibility": 4, - "ugliness": 2, "description": "You have a fin-like tail. It allows you to swim more quickly, but prevents wearing non-fabric pants. Slightly increases wet benefits.", "types": [ "TAIL" ], "prereqs": [ "TAIL_STUB" ], @@ -3048,7 +3046,6 @@ "name": { "str": "Long Tail" }, "points": 1, "visibility": 6, - "ugliness": 2, "description": "You have a long, graceful tail, like that of a big cat. It improves your balance, making your ability to dodge higher, but prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_STUB" ], @@ -3064,7 +3061,6 @@ "name": { "str": "Cattle Tail" }, "points": -1, "visibility": 6, - "ugliness": 2, "description": "You have a long tail with a tuft on the end. You find yourself instinctively swatting away flies with it, though it's not as effective at balancing you as you'd like. Prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_LONG" ], @@ -3079,7 +3075,6 @@ "name": { "str": "Rodent Tail" }, "points": 1, "visibility": 6, - "ugliness": 4, "description": "You have a long but hairless tail. It's a pretty effective balancing aid, but does look, uh, ratty. Prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_LONG", "TAIL_STUB" ], @@ -3094,7 +3089,6 @@ "name": { "str": "Thick Tail" }, "points": 1, "visibility": 8, - "ugliness": 2, "description": "You have a long, thick, lizardlike tail. It helps you balance a bit but also makes a serviceable whip. Prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_STUB" ], @@ -3116,7 +3110,6 @@ "name": { "str": "Raptor Tail" }, "points": 1, "visibility": 8, - "ugliness": 2, "description": "You have a long and semi-stiff lizardlike tail. You can't effectively lash it in combat, but it significantly improves your balance. Prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_STUB" ], @@ -3146,7 +3139,7 @@ "name": { "str": "Spiked Tail" }, "points": -1, "visibility": 6, - "ugliness": 3, + "ugliness": 1, "description": "You have a long tail that ends in a vicious stinger. It does not improve your balance at all, but allows for a powerful piercing attack. Prevents wearing non-fabric pants.", "types": [ "TAIL" ], "prereqs": [ "TAIL_LONG" ], @@ -3543,8 +3536,8 @@ "name": { "str": "Canine Ears" }, "points": 1, "visibility": 4, - "ugliness": 1, - "description": "Your ears have extended into long, pointed ones, like those of a canine. They enhance your hearing, allowing you to hear at greater distances.", + "ugliness": -2, + "description": "You've grown an extra pair of canine ears. They enhance your hearing, allowing you to hear at greater distances.", "types": [ "EARS" ], "category": [ "BEAST", "CATTLE", "CHIMERA" ], "changes_to": [ "LUPINE_EARS" ], @@ -3556,7 +3549,7 @@ "name": { "str": "Lupine Ears" }, "points": 1, "visibility": 4, - "ugliness": 1, + "ugliness": -2, "description": "Your hearing has evolved further and is now on par with that of wolves. You can hear things significantly farther away.", "types": [ "EARS" ], "category": [ "LUPINE" ], @@ -3568,7 +3561,8 @@ "name": { "str": "Feline Ears" }, "points": 1, "visibility": 4, - "description": "Your ears have extended into long, pointed, velvety ones, like those of a feline. You find it easier to tune in on sounds from afar.", + "ugliness": -2, + "description": "You've grown an extra pair of feline ears. You find it easier to tune in on sounds from afar. They are also very fluffy!", "types": [ "EARS" ], "category": [ "FELINE" ], "hearing_modifier": 1.25 @@ -3579,8 +3573,8 @@ "name": { "str": "Ursine Ears" }, "points": 1, "visibility": 4, - "ugliness": 1, - "description": "Your ears have grown longer and rounder, much like those of a bear. You can hear things a little farther away.", + "ugliness": -2, + "description": "You've grown an extra pair of ursine ears. You can hear things a little farther away.", "types": [ "EARS" ], "category": [ "URSINE" ], "hearing_modifier": 1.25 @@ -3591,7 +3585,7 @@ "name": { "str": "Pointed Ears" }, "points": 0, "visibility": 4, - "ugliness": 1, + "ugliness": -1, "description": "Your upper earlobes have grown noticeably higher. Fortunately, they don't get in the way of your headgear, much. Unfortunately, they also don't seem to help your hearing any.", "valid": false, "types": [ "EARS" ], @@ -3602,9 +3596,9 @@ "id": "MOUSE_EARS", "name": { "str": "Rodent Ears" }, "points": 1, - "visibility": 8, - "ugliness": 1, - "description": "Your ears are huge, round, and gray! They're rather fascinating, and help you hear from a much greater distance.", + "visibility": 6, + "ugliness": -2, + "description": "Your extra pair of ears are huge, round, and gray! They're rather fascinating, and help you hear from a much greater distance.", "valid": false, "types": [ "EARS" ], "category": [ "MOUSE", "RAT" ], From 378f57fb202c949727fc7403d139a26b7a13231a Mon Sep 17 00:00:00 2001 From: scarf Date: Tue, 26 Sep 2023 22:42:07 +0900 Subject: [PATCH 25/28] fix: lab README symlink (#3263) --- data/json/mapgen/lab/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/mapgen/lab/README.md b/data/json/mapgen/lab/README.md index 9fd0f753b651..f3f071860ee1 120000 --- a/data/json/mapgen/lab/README.md +++ b/data/json/mapgen/lab/README.md @@ -1 +1 @@ -doc/src/content/docs/en/mod/json/guides/map/lab.md \ No newline at end of file +../../../../doc/src/content/docs/en/mod/json/guides/map/lab.md \ No newline at end of file From 7f7adbad4a5a98950dbf901042bd688eee7675c3 Mon Sep 17 00:00:00 2001 From: 0Monet <146018959+0Monet@users.noreply.github.com> Date: Tue, 26 Sep 2023 20:40:39 +0200 Subject: [PATCH 26/28] Missing tile in horse ranches (#3274) * Update farm_horse.json * Update farm_horse_isherwood.json --- data/json/mapgen/farm_horse.json | 2 +- data/json/mapgen/isherwood_farms/farm_horse_isherwood.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/json/mapgen/farm_horse.json b/data/json/mapgen/farm_horse.json index f9b129d7c73f..66f7cb09c11e 100644 --- a/data/json/mapgen/farm_horse.json +++ b/data/json/mapgen/farm_horse.json @@ -61,7 +61,7 @@ "..%................................................WWvvWWWGGGGGWWWvvWW.//.%..................%..", "..%......................................................5/////.......//..%%%%HHH%%%%%%%%%%%%%..", "..%.....................X....AAAAAAAAAAWWWWWWW..X..........///////////..X....////............%..", - "..%......................///.A.........W;W;W;W................./////.. .////.////............%..", + "..%......................///.A.........W;W;W;W................./////....////.////............%..", "..%................./////////T.........W;;;;;W..................////////////.////........9...%..", "..%................////.////.A.........A;;;;;W..................///////////////....9.........%..", "..%.............////.........A.........K;;;;;W..........................///...............9..%..", diff --git a/data/json/mapgen/isherwood_farms/farm_horse_isherwood.json b/data/json/mapgen/isherwood_farms/farm_horse_isherwood.json index 5cc74f1ad32e..399e33102ae5 100644 --- a/data/json/mapgen/isherwood_farms/farm_horse_isherwood.json +++ b/data/json/mapgen/isherwood_farms/farm_horse_isherwood.json @@ -72,7 +72,7 @@ "..%................................................WWvvWWWGGGGGWWWvvWW.//.%..................%..", "..%......................................................5/////.......//..%%%%HHH%%%%%%%%%%%%%..", "..%.....................X....AAAAAAAAAAWWWWWWW..X..........///////////..X....////............%..", - "..%......................///.A.........W;W;W;W................./////.. .////.////............%..", + "..%......................///.A.........W;W;W;W................./////....////.////............%..", "..%................./////////T.........W;;;;;W..................////////////.////........9...%..", "..%................////.////.A.........A;;;;;W..................///////////////....9.........%..", "..%.............////.........A.........K;;;;;W..........................///...............9..%..", From ab83cb9fcef97945591bd92f62bbcf3a66172260 Mon Sep 17 00:00:00 2001 From: OrenAudeles Date: Tue, 26 Sep 2023 15:38:12 -0500 Subject: [PATCH 27/28] Update iexamine_elevator.cpp (#3276) gets rid of `-Werror=pedantic` compile error by removing unnecessary `;` --- src/iexamine_elevator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp index 27889bfe6b9e..fcc6274f9a6f 100644 --- a/src/iexamine_elevator.cpp +++ b/src/iexamine_elevator.cpp @@ -28,7 +28,7 @@ auto move_item( map &here, const tripoint &src, const tripoint &dest ) -> void here.add_item_or_charges( dest, *it ); it = here.i_rem( src, it ); } -}; +} namespace elevator { From e9a4cc57f555bfda19e4d3fca7819a2c3ea0ad08 Mon Sep 17 00:00:00 2001 From: jove Date: Wed, 27 Sep 2023 08:13:33 +0100 Subject: [PATCH 28/28] Shouldn't use uint --- src/armor_layers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/armor_layers.cpp b/src/armor_layers.cpp index 4854c439e53e..090160d10aab 100644 --- a/src/armor_layers.cpp +++ b/src/armor_layers.cpp @@ -490,7 +490,7 @@ void show_armor_layers_ui( Character &who ) int leftListLines = 0; int rightListLines = 0; - std::vector tmp_worn; + std::vector tmp_worn; std::array armor_cat = {{ _( "Torso" ), _( "Head" ), _( "Eyes" ), _( "Mouth" ), _( "L. Arm" ), _( "R. Arm" ), _( "L. Hand" ), _( "R. Hand" ), _( "L. Leg" ), _( "R. Leg" ), _( "L. Foot" ),