From d3c9a335f2fbbb7c5338457b6cd1d8f35ad0ea2a Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 25 Sep 2023 01:00:54 +0900 Subject: [PATCH 01/20] 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 02/20] 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 03/20] 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 04/20] 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 05/20] 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 06/20] 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 07/20] 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 08/20] 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 09/20] 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 10/20] 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 11/20] 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 12/20] 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 13/20] 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 14/20] 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 15/20] 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 bf8de423dacee5f5fedb66c3a56cd20e3a816941 Mon Sep 17 00:00:00 2001 From: OrenAudeles Date: Tue, 26 Sep 2023 17:17:06 -0500 Subject: [PATCH 16/20] perf: speed up item::has_flag calls (#3277) * perf: speed up item::has_flag calls * astyle --- src/item.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index effb3c1d323b..b5a1a6e14a57 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -5329,26 +5329,27 @@ bool item::has_own_flag( const std::string &f ) const bool item::has_flag( const std::string &f ) const { - bool ret = false; - - if( json_flag::get( f ).inherit() ) { - for( const item *e : is_gun() ? gunmods() : toolmods() ) { - // gunmods fired separately do not contribute to base gun flags - if( !e->is_gun() && e->has_flag( f ) ) { - return true; - } - } + // Check if we have any gun/toolmods with the flag, and if we do + // check if that flag should be inherited. + // `json_flag::get` is pretty expensive so it's faster to do it + // last as frequently there are no gun/toolmods with the flag f + auto mods = is_gun() ? gunmods() : toolmods(); + if( + std::any_of( mods.begin(), mods.end(), + [&f]( const item * e ) { + return ( !e->is_gun() && e->has_flag( f ) ); + } + ) && json_flag::get( f ).inherit() ) { + return true; } // other item type flags - ret = type->has_flag( f ); - if( ret ) { - return ret; + if( type->has_flag( f ) ) { + return true; } // now check for item specific flags - ret = has_own_flag( f ); - return ret; + return has_own_flag( f ); } bool item::has_flag( const flag_str_id &flag ) const From 09f36866078d33b8eb68f010c5a8840d93c21fa7 Mon Sep 17 00:00:00 2001 From: scarf Date: Wed, 27 Sep 2023 09:35:08 +0900 Subject: [PATCH 17/20] perf(map): inline `sm_to_ms_copy` (#3278) * refactor: trailing auto returns * refactor: add line breaks my eyes hurt distinguishing them! * refactor: use anonymous namespace looks better imo * perf: inline `sm_to_ms_copy` see: https://github.com/CleverRaven/Cataclysm-DDA/pull/66889 Co-authored-by: Andrew Krieger --------- Co-authored-by: Andrew Krieger --- src/coordinate_conversions.cpp | 67 ++++++++--------- src/coordinate_conversions.h | 130 ++++++++++++++++++++++++--------- 2 files changed, 128 insertions(+), 69 deletions(-) diff --git a/src/coordinate_conversions.cpp b/src/coordinate_conversions.cpp index 623a94cc35d5..9c4d4ae018ab 100644 --- a/src/coordinate_conversions.cpp +++ b/src/coordinate_conversions.cpp @@ -1,8 +1,9 @@ #include "coordinate_conversions.h" -#include "game_constants.h" +namespace +{ -static int divide( int v, int m ) +auto divide( int v, int m ) -> int { if( v >= 0 ) { return v / m; @@ -10,19 +11,22 @@ static int divide( int v, int m ) return ( v - m + 1 ) / m; } -static int divide( int v, int m, int &r ) +auto divide( int v, int m, int &r ) -> int { const int result = divide( v, m ); r = v - result * m; return result; } -point omt_to_om_copy( point p ) +} // namespace + + +auto omt_to_om_copy( point p ) -> point { return point( divide( p.x, OMAPX ), divide( p.y, OMAPY ) ); } -tripoint omt_to_om_copy( const tripoint &p ) +auto omt_to_om_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, OMAPX ), divide( p.y, OMAPY ), p.z ); } @@ -33,22 +37,22 @@ void omt_to_om( int &x, int &y ) y = divide( y, OMAPY ); } -point omt_to_om_remain( int &x, int &y ) +auto omt_to_om_remain( int &x, int &y ) -> point { return point( divide( x, OMAPX, x ), divide( y, OMAPY, y ) ); } -point om_to_omt_copy( point p ) +auto om_to_omt_copy( point p ) -> point { return point( p.x * OMAPX, p.y * OMAPY ); } -point sm_to_omt_copy( point p ) +auto sm_to_omt_copy( point p ) -> point { return point( divide( p.x, 2 ), divide( p.y, 2 ) ); } -tripoint sm_to_omt_copy( const tripoint &p ) +auto sm_to_omt_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, 2 ), divide( p.y, 2 ), p.z ); } @@ -59,17 +63,17 @@ void sm_to_omt( int &x, int &y ) y = divide( y, 2 ); } -point sm_to_omt_remain( int &x, int &y ) +auto sm_to_omt_remain( int &x, int &y ) -> point { return point( divide( x, 2, x ), divide( y, 2, y ) ); } -point sm_to_om_copy( point p ) +auto sm_to_om_copy( point p ) -> point { return point( divide( p.x, 2 * OMAPX ), divide( p.y, 2 * OMAPY ) ); } -tripoint sm_to_om_copy( const tripoint &p ) +auto sm_to_om_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, 2 * OMAPX ), divide( p.y, 2 * OMAPY ), p.z ); } @@ -80,22 +84,22 @@ void sm_to_om( int &x, int &y ) y = divide( y, 2 * OMAPY ); } -point sm_to_om_remain( int &x, int &y ) +auto sm_to_om_remain( int &x, int &y ) -> point { return point( divide( x, 2 * OMAPX, x ), divide( y, 2 * OMAPY, y ) ); } -point omt_to_ms_copy( point p ) +auto omt_to_ms_copy( point p ) -> point { return point( p.x * 2 * SEEX, p.y * 2 * SEEY ); } -point omt_to_sm_copy( point p ) +auto omt_to_sm_copy( point p ) -> point { return point( p.x * 2, p.y * 2 ); } -tripoint omt_to_sm_copy( const tripoint &p ) +auto omt_to_sm_copy( const tripoint &p ) -> tripoint { return tripoint( p.x * 2, p.y * 2, p.z ); } @@ -106,12 +110,12 @@ void omt_to_sm( int &x, int &y ) y *= 2; } -point om_to_sm_copy( point p ) +auto om_to_sm_copy( point p ) -> point { return point( p.x * 2 * OMAPX, p.y * 2 * OMAPX ); } -tripoint om_to_sm_copy( const tripoint &p ) +auto om_to_sm_copy( const tripoint &p ) -> tripoint { return tripoint( p.x * 2 * OMAPX, p.y * 2 * OMAPX, p.z ); } @@ -122,12 +126,12 @@ void om_to_sm( int &x, int &y ) y *= 2 * OMAPY; } -point ms_to_sm_copy( point p ) +auto ms_to_sm_copy( point p ) -> point { return point( divide( p.x, SEEX ), divide( p.y, SEEY ) ); } -tripoint ms_to_sm_copy( const tripoint &p ) +auto ms_to_sm_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, SEEX ), divide( p.y, SEEY ), p.z ); } @@ -138,20 +142,11 @@ void ms_to_sm( int &x, int &y ) y = divide( y, SEEY ); } -point ms_to_sm_remain( int &x, int &y ) +auto ms_to_sm_remain( int &x, int &y ) -> point { return point( divide( x, SEEX, x ), divide( y, SEEY, y ) ); } -point sm_to_ms_copy( point p ) -{ - return point( p.x * SEEX, p.y * SEEY ); -} - -tripoint sm_to_ms_copy( const tripoint &p ) -{ - return tripoint( p.x * SEEX, p.y * SEEY, p.z ); -} void sm_to_ms( int &x, int &y ) { @@ -159,12 +154,12 @@ void sm_to_ms( int &x, int &y ) y *= SEEY; } -point ms_to_omt_copy( point p ) +auto ms_to_omt_copy( point p ) -> point { return point( divide( p.x, SEEX * 2 ), divide( p.y, SEEY * 2 ) ); } -tripoint ms_to_omt_copy( const tripoint &p ) +auto ms_to_omt_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, SEEX * 2 ), divide( p.y, SEEY * 2 ), p.z ); } @@ -175,22 +170,22 @@ void ms_to_omt( int &x, int &y ) y = divide( y, SEEY * 2 ); } -point ms_to_omt_remain( int &x, int &y ) +auto ms_to_omt_remain( int &x, int &y ) -> point { return point( divide( x, SEEX * 2, x ), divide( y, SEEY * 2, y ) ); } -tripoint omt_to_seg_copy( const tripoint &p ) +auto omt_to_seg_copy( const tripoint &p ) -> tripoint { return tripoint( divide( p.x, SEG_SIZE ), divide( p.y, SEG_SIZE ), p.z ); } -point sm_to_mmr_remain( int &x, int &y ) +auto sm_to_mmr_remain( int &x, int &y ) -> point { return point( divide( x, MM_REG_SIZE, x ), divide( y, MM_REG_SIZE, y ) ); } -tripoint mmr_to_sm_copy( const tripoint &p ) +auto mmr_to_sm_copy( const tripoint &p ) -> tripoint { return tripoint( p.x * MM_REG_SIZE, p.y * MM_REG_SIZE, p.z ); } diff --git a/src/coordinate_conversions.h b/src/coordinate_conversions.h index 23b9d13c55cf..82eabf2124e3 100644 --- a/src/coordinate_conversions.h +++ b/src/coordinate_conversions.h @@ -2,6 +2,7 @@ #ifndef CATA_SRC_COORDINATE_CONVERSIONS_H #define CATA_SRC_COORDINATE_CONVERSIONS_H +#include "game_constants.h" #include "point.h" /** @@ -38,146 +39,209 @@ */ // overmap terrain to overmap -point omt_to_om_copy( point p ); -tripoint omt_to_om_copy( const tripoint &p ); +auto omt_to_om_copy( point p ) -> point; + +auto omt_to_om_copy( const tripoint &p ) -> tripoint; + void omt_to_om( int &x, int &y ); + inline void omt_to_om( point &p ) { omt_to_om( p.x, p.y ); } + inline void omt_to_om( tripoint &p ) { omt_to_om( p.x, p.y ); } -point omt_to_om_remain( int &x, int &y ); -inline point omt_to_om_remain( point &p ) + +auto omt_to_om_remain( int &x, int &y ) -> point; + +inline auto omt_to_om_remain( point &p ) -> point { return omt_to_om_remain( p.x, p.y ); } + // overmap to overmap terrain -point om_to_omt_copy( point p ); +auto om_to_omt_copy( point p ) -> point; + // submap to overmap terrain -point sm_to_omt_copy( point p ); -tripoint sm_to_omt_copy( const tripoint &p ); +auto sm_to_omt_copy( point p ) -> point; + +auto sm_to_omt_copy( const tripoint &p ) -> tripoint; + void sm_to_omt( int &x, int &y ); + inline void sm_to_omt( point &p ) { sm_to_omt( p.x, p.y ); } + inline void sm_to_omt( tripoint &p ) { sm_to_omt( p.x, p.y ); } -point sm_to_omt_remain( int &x, int &y ); -inline point sm_to_omt_remain( point &p ) + +auto sm_to_omt_remain( int &x, int &y ) -> point; + +inline auto sm_to_omt_remain( point &p ) -> point { return sm_to_omt_remain( p.x, p.y ); } + // submap to overmap, basically: x / (OMAPX * 2) -point sm_to_om_copy( point p ); -tripoint sm_to_om_copy( const tripoint &p ); +auto sm_to_om_copy( point p ) -> point; + +auto sm_to_om_copy( const tripoint &p ) -> tripoint; + void sm_to_om( int &x, int &y ); + inline void sm_to_om( point &p ) { sm_to_om( p.x, p.y ); } + inline void sm_to_om( tripoint &p ) { sm_to_om( p.x, p.y ); } -point sm_to_om_remain( int &x, int &y ); -inline point sm_to_om_remain( point &p ) + +auto sm_to_om_remain( int &x, int &y ) -> point; + +inline auto sm_to_om_remain( point &p ) -> point { return sm_to_om_remain( p.x, p.y ); } + // overmap terrain to submap, basically: x *= 2 -inline int omt_to_sm_copy( int a ) +inline auto omt_to_sm_copy( int a ) -> int { return 2 * a; } -point omt_to_sm_copy( point p ); -tripoint omt_to_sm_copy( const tripoint &p ); + +auto omt_to_sm_copy( point p ) -> point; + +auto omt_to_sm_copy( const tripoint &p ) -> tripoint; + void omt_to_sm( int &x, int &y ); + inline void omt_to_sm( point &p ) { omt_to_sm( p.x, p.y ); } + inline void omt_to_sm( tripoint &p ) { omt_to_sm( p.x, p.y ); } + // overmap terrain to map square -point omt_to_ms_copy( point p ); +auto omt_to_ms_copy( point p ) -> point; + // overmap to submap, basically: x *= 2 * OMAPX -point om_to_sm_copy( point p ); -tripoint om_to_sm_copy( const tripoint &p ); +auto om_to_sm_copy( point p ) -> point; + +auto om_to_sm_copy( const tripoint &p ) -> tripoint; + void om_to_sm( int &x, int &y ); + inline void om_to_sm( point &p ) { om_to_sm( p.x, p.y ); } + inline void om_to_sm( tripoint &p ) { om_to_sm( p.x, p.y ); } + // map squares to submap, basically: x /= SEEX -point ms_to_sm_copy( point p ); -tripoint ms_to_sm_copy( const tripoint &p ); +auto ms_to_sm_copy( point p ) -> point; + +auto ms_to_sm_copy( const tripoint &p ) -> tripoint; + void ms_to_sm( int &x, int &y ); + inline void ms_to_sm( point &p ) { ms_to_sm( p.x, p.y ); } + inline void ms_to_sm( tripoint &p ) { ms_to_sm( p.x, p.y ); } -point ms_to_sm_remain( int &x, int &y ); -inline point ms_to_sm_remain( point &p ) + +auto ms_to_sm_remain( int &x, int &y ) -> point; + +inline auto ms_to_sm_remain( point &p ) -> point { return ms_to_sm_remain( p.x, p.y ); } -inline tripoint ms_to_sm_remain( tripoint &p ) + +inline auto ms_to_sm_remain( tripoint &p ) -> tripoint { return tripoint( ms_to_sm_remain( p.x, p.y ), p.z ); } + // submap back to map squares, basically: x *= SEEX // Note: this gives you the map square coordinates of the top-left corner // of the given submap. -point sm_to_ms_copy( point p ); -tripoint sm_to_ms_copy( const tripoint &p ); +inline auto sm_to_ms_copy( point p ) -> point +{ + return point( p.x * SEEX, p.y * SEEY ); +} + +inline auto sm_to_ms_copy( const tripoint &p ) -> tripoint +{ + return tripoint( p.x * SEEX, p.y * SEEY, p.z ); +} + void sm_to_ms( int &x, int &y ); + inline void sm_to_ms( point &p ) { sm_to_ms( p.x, p.y ); } + inline void sm_to_ms( tripoint &p ) { sm_to_ms( p.x, p.y ); } + // map squares to overmap terrain, basically: x /= SEEX * 2 -point ms_to_omt_copy( point p ); -tripoint ms_to_omt_copy( const tripoint &p ); + +auto ms_to_omt_copy( point p ) -> point; + +auto ms_to_omt_copy( const tripoint &p ) -> tripoint; + void ms_to_omt( int &x, int &y ); + inline void ms_to_omt( point &p ) { ms_to_omt( p.x, p.y ); } + inline void ms_to_omt( tripoint &p ) { ms_to_omt( p.x, p.y ); } -point ms_to_omt_remain( int &x, int &y ); -inline point ms_to_omt_remain( point &p ) + +auto ms_to_omt_remain( int &x, int &y ) -> point; + +inline auto ms_to_omt_remain( point &p ) -> point { return ms_to_omt_remain( p.x, p.y ); } + // overmap terrain to map segment. -tripoint omt_to_seg_copy( const tripoint &p ); +auto omt_to_seg_copy( const tripoint &p ) -> tripoint; + // Submap to memory map region. -point sm_to_mmr_remain( int &x, int &y ); +auto sm_to_mmr_remain( int &x, int &y ) -> point; + // Memory map region to submap. // Note: this produces sm coords of top-left corner of the region. -tripoint mmr_to_sm_copy( const tripoint &p ); +auto mmr_to_sm_copy( const tripoint &p ) -> tripoint; #endif // CATA_SRC_COORDINATE_CONVERSIONS_H From 79039da47836adfa3a229e43c56ac445c77cf02d Mon Sep 17 00:00:00 2001 From: Olanti Date: Wed, 27 Sep 2023 03:35:09 +0300 Subject: [PATCH 18/20] Properly remove stale test user dir (#3270) * BNify * Add warning * Add remove_tree and use it for test user dir --- src/filesystem.cpp | 15 +++++++++++++++ src/filesystem.h | 6 ++++++ tests/filesystem_test.cpp | 14 +++++++++----- tests/test_main.cpp | 8 ++++++-- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index be3bd83a8617..c23474b4c666 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -1,6 +1,7 @@ #include "filesystem.h" // FILE I/O +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +119,19 @@ bool remove_directory( const std::string &path ) #endif } +bool remove_tree( const std::string &path ) +{ + try { + // TODO: C++20 - path constructor should be able to take the string as is + auto fs_path = std::filesystem::u8path( path ); + std::filesystem::remove_all( fs_path ); + } catch( std::filesystem::filesystem_error &e ) { + dbg( DL::Error ) << "remove_tree [" << path << "] failed with \"" << e.what() << "\"."; + return false; + } + return true; +} + const char *cata_files::eol() { #if defined(_WIN32) diff --git a/src/filesystem.h b/src/filesystem.h index 04d328940d74..86c5f6a7fb55 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -30,6 +30,12 @@ bool remove_file( const std::string &path ); * @return true on success, false on failure (e.g. directory is not empty). */ bool remove_directory( const std::string &path ); +/** + * Remove a directory and all its children. + * @return true on success or if the directory did not exist, + * false on failure to remove (e.g. no permissions, directory is being used). + */ +bool remove_tree( const std::string &path ); /** * Rename a file, overwriting the target. Does not overwrite directories. * @return true on success, false on failure. diff --git a/tests/filesystem_test.cpp b/tests/filesystem_test.cpp index 49a7ccc8d234..7e0102cb8f43 100644 --- a/tests/filesystem_test.cpp +++ b/tests/filesystem_test.cpp @@ -136,13 +136,17 @@ static void filesystem_test_group( int serial, const std::string &s1, const std: // Can't delete directory with files REQUIRE( !remove_directory( dir1 ) ); + REQUIRE( dir_exist( dir1 ) ); + + // Unless we use remove_tree + REQUIRE( remove_tree( dir1 ) ); + REQUIRE( !dir_exist( dir1 ) ); + + // Removing non-existent tree is not an error + REQUIRE( remove_tree( dir1 ) ); + REQUIRE( remove_tree( dir2 ) ); // Clean up - REQUIRE( remove_file( file1_1 ) ); - REQUIRE( remove_file( file1_2 ) ); - REQUIRE( remove_file( file2_1 ) ); - REQUIRE( remove_directory( dir2 ) ); - REQUIRE( remove_directory( dir1 ) ); REQUIRE( remove_directory( base ) ); } diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 2012f88f4a73..ae2533bcddf1 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -99,7 +99,9 @@ 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( !remove_tree( user_dir ) ) { + assert( !"Unable to remove user_dir directory. Check permissions." ); + } if( !assure_dir_exist( user_dir ) ) { assert( !"Unable to make user_dir directory. Check permissions." ); } @@ -294,9 +296,11 @@ int main( int argc, const char *argv[] ) // Note: this must not be invoked before all DDA-specific flags are stripped from arg_vec! int result = session.applyCommandLine( arg_vec.size(), arg_vec.data() ); if( result != 0 || session.configData().showHelp ) { - cata_printf( "CataclysmDDA specific options:\n" ); + cata_printf( "Cataclysm: BN specific options:\n" ); cata_printf( " --mods= Loads the list of mods before executing tests.\n" ); cata_printf( " --user-dir= Set user dir (where test world will be created).\n" ); + cata_printf( " Don't use any existing folder you care about,\n" ); + cata_printf( " all contents will be erased!\n" ); cata_printf( " -D, --drop-world Don't save the world on test failure.\n" ); cata_printf( " --option_overrides=n:v[,…] Name-value pairs of game options for tests.\n" ); cata_printf( " (overrides config/options.json values)\n" ); From f7ecf91aa1a2efd890682fbddc0fec312b28523d Mon Sep 17 00:00:00 2001 From: scarf Date: Fri, 15 Sep 2023 18:50:52 +0900 Subject: [PATCH 19/20] build: tracy integration --- CMakeLists.txt | 17 +++++++++++++++++ src/SetupLibrary.cmake | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 700800055b7a..355a358827ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ option(USE_PCH_HEADER "Use precompiled PCH header." "OFF") option(JSON_FORMAT "Build JSON formatter" "OFF") option(CATA_CCACHE "Try to find and build with ccache" "ON") option(CATA_CLANG_TIDY_PLUGIN "Build Cata's custom clang-tidy plugin" "OFF") +option(TRACY "Use Tracy profiler" "OFF") set(CATA_CLANG_TIDY_INCLUDE_DIR "" CACHE STRING "Path to internal clang-tidy headers required for plugin (e.g. ClangTidy.h)") @@ -228,6 +229,7 @@ message(STATUS "SOUND : ${SOUND}") message(STATUS "LUA : ${LUA}") message(STATUS "BACKTRACE : ${BACKTRACE}") message(STATUS "LIBBACKTRACE : ${LIBBACKTRACE}") +message(STATUS "TRACY : ${TRACY}") message(STATUS "USE_HOME_DIR : ${USE_HOME_DIR}\n") message(STATUS "UNITY_BUILD : ${USE_UNITY_BUILD}") @@ -288,6 +290,21 @@ endif () set(CMAKE_THREAD_PREFER_PTHREAD True) find_package(Threads REQUIRED) +if (TRACY) + include(FetchContent) + add_compile_definitions(CATA_PROFILE) + + FetchContent_Declare( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG master + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE) + FetchContent_MakeAvailable(tracy) + + target_compile_options(TracyClient PRIVATE "-Wno-everything") +endif () + # Check for build types and libraries if (TILES) # Find SDL, SDL_ttf & SDL_image for graphical install diff --git a/src/SetupLibrary.cmake b/src/SetupLibrary.cmake index 1aa47165f4d4..f9470c7a425c 100644 --- a/src/SetupLibrary.cmake +++ b/src/SetupLibrary.cmake @@ -44,4 +44,8 @@ function (setup_library TARGET) target_link_libraries(${TARGET} backtrace) endif () + if (TRACY) + target_link_libraries(${TARGET} TracyClient) + endif () + endfunction () From 65894d4ccc5f6225e9594a77032f22bed05b0d4b Mon Sep 17 00:00:00 2001 From: scarf Date: Wed, 27 Sep 2023 10:37:58 +0900 Subject: [PATCH 20/20] docs: tracy guide --- .../docs/en/dev/guides/building/cmake.md | 4 ++ doc/src/content/docs/en/dev/guides/tracy.md | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 doc/src/content/docs/en/dev/guides/tracy.md diff --git a/doc/src/content/docs/en/dev/guides/building/cmake.md b/doc/src/content/docs/en/dev/guides/building/cmake.md index 5907f9519a6a..654608a3bbd5 100644 --- a/doc/src/content/docs/en/dev/guides/building/cmake.md +++ b/doc/src/content/docs/en/dev/guides/building/cmake.md @@ -354,6 +354,10 @@ much faster. [libbacktrace]: https://github.com/ianlancetaylor/libbacktrace +- TRACY=`` + +Use tracy profiler. See [Profiling with tracy](../tracy.md) for more information. + - GIT_BINARY=`` Override default Git binary name or path. diff --git a/doc/src/content/docs/en/dev/guides/tracy.md b/doc/src/content/docs/en/dev/guides/tracy.md new file mode 100644 index 000000000000..32a3b9a15b23 --- /dev/null +++ b/doc/src/content/docs/en/dev/guides/tracy.md @@ -0,0 +1,37 @@ +--- +title: Profiling with tracy +--- + +![](https://camo.githubusercontent.com/addc8ec15d303dd7084724123e18c3c47fbe721e000c6e2c58a2ac1185badf1f/68747470733a2f2f6d656469612e646973636f72646170702e6e65742f6174746163686d656e74732f3833303931363435313531373835373839342f313135323137353437343038353139393837322f696d6167652e706e673f77696474683d31303939266865696768743d363235) + +Tracy is a tool for profiling and debugging your code. It is separated into two parts: server and +client. Server is a part of your application that collects data and client is a GUI that displays +it. + +## Install tracy client + +### Linux, MacOS + +```sh +make -j 10 -C profiler/build/unix LEGACY=1 release +``` + +Clone and build from source. For more instructions, check +[tracy's github actions](https://github.com/wolfpld/tracy/blob/master/.github/workflows/gcc.yml). + +:::note{title="for X11"} + +tracy uses wayland by default, if you want to use X11, you need to add `LEGACY=1` flag. + +::: + +### Windows + +![image](https://github.com/cataclysmbnteam/Cataclysm-BN/assets/54838975/b6f73c09-969c-4305-b8fb-070d14fb834a) + +Download pre-compiled executable from . + +## Build BN with tracy server + +Build on cmake with `-D TRACY=ON` flag. See +[CMake options](building/cmake.md#cataclysmbn-specific-options) for more information.